Completed
Push — master ( 1c0988...942beb )
by Fabio
07:52
created

TClientScriptManager::getPradoScriptAssetPath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
/**
3
 * TClientScriptManager and TClientSideOptions class file.
4
 *
5
 * @author Qiang Xue <[email protected]>
6
 * @author Gabor Berczi <[email protected]> (lazyload additions & progressive rendering)
7
 * @link https://github.com/pradosoft/prado4
8
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
9
 * @license https://github.com/pradosoft/prado4/blob/master/LICENSE
10
 * @package Prado\Web\UI
11
 */
12
13
namespace Prado\Web\UI;
14
use Prado\Prado;
15
use Prado\TApplicationMode;
16
use Prado\Exceptions\TInvalidDataValueException;
17
use Prado\Exceptions\TInvalidOperationException;
18
use Prado\Web\Javascripts\TJavaScript;
19
use Prado\Web\UI\ActiveControls\ICallbackEventHandler;
20
use Prado\Web\THttpUtility;
21
22
/**
23
 * TClientScriptManager class.
24
 *
25
 * TClientScriptManager manages javascript and CSS stylesheets for a page.
26
 *
27
 * @author Qiang Xue <[email protected]>
28
 * @author Gabor Berczi <[email protected]> (lazyload additions & progressive rendering)
29
 * @package Prado\Web\UI
30
 * @since 3.0
31
 */
32
class TClientScriptManager extends \Prado\TApplicationComponent
33
{
34
	/**
35
	 * file containing javascript packages and their cross dependencies
36
	 */
37
	const PACKAGES_FILE='Web/Javascripts/packages.php';
38
	/**
39
	 * file containing css packages and their cross dependencies
40
	 */
41
	const CSS_PACKAGES_FILE='Web/Javascripts/css-packages.php';
42
	/**
43
	 * @var TPage page who owns this manager
44
	 */
45
	private $_page;
46
	/**
47
	 * @var array registered hidden fields, indexed by hidden field names
48
	 */
49
	private $_hiddenFields=array();
50
	/**
51
	 * @var array javascript blocks to be rendered at the beginning of the form
52
	 */
53
	private $_beginScripts=array();
54
	/**
55
	 * @var array javascript blocks to be rendered at the end of the form
56
	 */
57
	private $_endScripts=array();
58
	/**
59
	 * @var array javascript files to be rendered in the form
60
	 */
61
	private $_scriptFiles=array();
62
	/**
63
	 * @var array javascript files to be rendered in page head section
64
	 */
65
	private $_headScriptFiles=array();
66
	/**
67
	 * @var array javascript blocks to be rendered in page head section
68
	 */
69
	private $_headScripts=array();
70
	/**
71
	 * @var array CSS files
72
	 */
73
	private $_styleSheetFiles=array();
74
	/**
75
	 * @var array CSS declarations
76
	 */
77
	private $_styleSheets=array();
78
	/**
79
	 * @var array registered PRADO script libraries
80
	 */
81
	private $_registeredScripts=array();
82
	/**
83
	 * Client-side javascript library dependencies, loads from PACKAGES_FILE;
84
	 * @var array
85
	 */
86
	private static $_scripts;
87
	/**
88
	 * Client-side javascript library packages, loads from PACKAGES_FILE;
89
	 * @var array
90
	 */
91
	private static $_scriptsPackages;
92
	/**
93
	 * Client-side javascript library source folders, loads from PACKAGES_FILE;
94
	 * @var array
95
	 */
96
	private static $_scriptsFolders;
97
	/**
98
	 * @var array registered PRADO style libraries
99
	 */
100
	private $_registeredStyles=array();
101
	/**
102
	 * Client-side style library dependencies, loads from CSS_PACKAGES_FILE;
103
	 * @var array
104
	 */
105
	private static $_styles;
106
	/**
107
	 * Client-side style library packages, loads from CSS_PACKAGES_FILE;
108
	 * @var array
109
	 */
110
	private static $_stylesPackages;
111
	/**
112
	 * Client-side style library folders, loads from CSS_PACKAGES_FILE;
113
	 * @var array
114
	 */
115
	private static $_stylesFolders;
116
117
	private $_renderedHiddenFields;
118
119
	private $_renderedScriptFiles=array();
120
121
	private $_expandedScripts;
122
	private $_expandedStyles;
123
124
	/**
125
	 * Constructor.
126
	 * @param TPage page that owns this client script manager
127
	 */
128
	public function __construct(TPage $owner)
129
	{
130
		$this->_page=$owner;
131
	}
132
133
	/**
134
	 * @return boolean whether THead is required in order to render CSS and js within head
135
	 * @since 3.1.1
136
	 */
137
	public function getRequiresHead()
138
	{
139
		return count($this->_styleSheetFiles) || count($this->_styleSheets)
140
			|| count($this->_headScriptFiles) || count($this->_headScripts);
141
	}
142
143
	public static function getPradoPackages()
144
	{
145
		return self::$_scriptsPackages;
146
	}
147
148
	public static function getPradoScripts()
149
	{
150
		return self::$_scripts;
151
	}
152
153
	/**
154
	 * Registers Prado javascript by library name. See "Web/Javascripts/packages.php"
155
	 * for library names.
156
	 * @param string script library name.
157
	 */
158
	public function registerPradoScript($name)
159
	{
160
		$this->registerPradoScriptInternal($name);
161
		$params=func_get_args();
162
		$this->_page->registerCachingAction('Page.ClientScript','registerPradoScript',$params);
163
	}
164
165
	/**
166
	 * Registers a Prado javascript library to be loaded.
167
	 */
168
	protected function registerPradoScriptInternal($name)
169
	{
170
		// $this->checkIfNotInRender();
171
		if(!isset($this->_registeredScripts[$name]))
172
		{
173
			if(self::$_scripts === null)
174
			{
175
				$packageFile = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::PACKAGES_FILE;
176
				list($folders, $packages, $deps)= include($packageFile);
177
				self::$_scriptsFolders = $folders;
178
				self::$_scripts = $deps;
179
				self::$_scriptsPackages = $packages;
180
			}
181
182
			if (isset(self::$_scripts[$name]))
183
				$this->_registeredScripts[$name]=true;
184
			else
185
				throw new TInvalidOperationException('csmanager_pradoscript_invalid',$name);
186
187
			if(($packages=array_keys($this->_registeredScripts))!==array())
188
			{
189
				$packagesUrl=array();
190
				$isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug;
191
				foreach ($packages as $p)
192
				{
193
					foreach (self::$_scripts[$p] as $dep)
194
					{
195
						foreach (self::$_scriptsPackages[$dep] as $script)
196
						{
197
							if (!isset($this->_expandedScripts[$script]))
198
							{
199
								list($base, $subPath) = $this->getScriptPackageFolder($script);
200
								list($path, $baseUrl) = $this->getPackagePathUrl($base);
201
202
								$this->_expandedScripts[$script] = true;
203
								if($isDebug)
204
								{
205
									if (!in_array($url=$baseUrl.'/'.$subPath, $packagesUrl))
206
										$packagesUrl[]=$url;
207
								} else {
208
									if (!in_array($url=$baseUrl.'/min/'.$subPath, $packagesUrl))
209
									{
210
										if(!is_file($filePath=$path.'/min/'.$subPath))
211
										{
212
											$dirPath=dirname($filePath);
213
											if(!is_dir($dirPath))
214
												mkdir($dirPath, PRADO_CHMOD, true);
215
											file_put_contents($filePath, TJavaScript::JSMin(file_get_contents($base.'/'.$subPath)));
216
											chmod($filePath, PRADO_CHMOD);
217
										}
218
										$packagesUrl[]=$url;
219
									}
220
								}
221
							}
222
						}
223
					}
224
				}
225
				foreach($packagesUrl as $url)
226
					$this->registerScriptFile($url,$url);
227
			}
228
		}
229
	}
230
231
	/**
232
	 * @return string Prado javascript library base asset url.
233
	 */
234
	public function getPradoScriptAssetUrl($script='prado')
235
	{
236
		if(!array_key_exists($script, self::$_scriptsFolders))
237
			throw new TInvalidOperationException('csmanager_pradostyle_invalid',$script);
238
		
239
		$base = Prado::getPathOfNameSpace(self::$_scriptsFolders[$script]);
240
		$assets = Prado::getApplication()->getAssetManager();
241
		return $assets->getPublishedUrl($base);
242
	}
243
244
	/**
245
	 * @return string Prado javascript library base asset path in local filesystem.
246
	 */
247
	public function getPradoScriptAssetPath($script='prado')
248
	{
249
		if(!array_key_exists($script, self::$_scriptsFolders))
250
			throw new TInvalidOperationException('csmanager_pradostyle_invalid',$script);
251
		
252
		$base = Prado::getPathOfNameSpace(self::$_scriptsFolders[$script]);
253
		$assets = Prado::getApplication()->getAssetManager();
254
		return $assets->getPublishedPath($base);
255
	}
256
257
	/**
258
	 * Returns the URLs of all script files referenced on the page
259
	 * @return array Combined list of all script urls used in the page
260
	 */
261
	public function getScriptUrls()
262
	{
263
		$scripts = array_values($this->_headScriptFiles);
264
		$scripts = array_merge($scripts, array_values($this->_scriptFiles));
265
		$scripts = array_unique($scripts);
266
267
		return $scripts;
268
	}
269
270
	/**
271
	 * @param string javascript or css package path.
272
	 * @return array tuple($path,$url).
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
273
	 */
274
	protected function getPackagePathUrl($base)
275
	{
276
		$assets = Prado::getApplication()->getAssetManager();
277
		if(strpos($base, $assets->getBaseUrl())===false)
278
		{
279
			if(($dir = Prado::getPathOfNameSpace($base)) !== null) {
280
				$base = $dir;
281
			}
282
			return array($assets->getPublishedPath($base), $assets->publishFilePath($base));
283
		}
284
		else
285
		{
286
			return array($assets->getBasePath().str_replace($assets->getBaseUrl(),'',$base), $base);
287
		}
288
	}
289
290
	/**
291
	 * @param string javascript package source folder path.
292
	 * @return array tuple($basepath,$subpath).
293
	 */
294
	protected function getScriptPackageFolder($script)
295
	{
296
		list($base, $subPath) = explode("/", $script, 2);
297
298
		if(!array_key_exists($base, self::$_scriptsFolders))
299
			throw new TInvalidOperationException('csmanager_pradostyle_invalid',$base);
300
		
301
		return array(self::$_scriptsFolders[$base], $subPath);
302
	}
303
304
	/**
305
	 * @param string css package source folder path.
306
	 * @return array tuple($basepath,$subpath).
307
	 */
308
	protected function getStylePackageFolder($script)
309
	{
310
		list($base, $subPath) = explode("/", $script, 2);
311
312
		if(!array_key_exists($base, self::$_stylesFolders))
313
			throw new TInvalidOperationException('csmanager_pradostyle_invalid',$base);
314
		
315
		return array(self::$_stylesFolders[$base], $subPath);
316
	}
317
318
	/**
319
	 * Returns javascript statement that create a new callback request object.
320
	 * @param ICallbackEventHandler callback response handler
321
	 * @param array additional callback options
322
	 * @return string javascript statement that creates a new callback request.
323
	 */
324
	public function getCallbackReference(ICallbackEventHandler $callbackHandler, $options=null)
325
	{
326
		$options = !is_array($options) ? array() : $options;
327
		$class = new \ReflectionClass($callbackHandler);
0 ignored issues
show
Unused Code introduced by
$class is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
328
		$clientSide = $callbackHandler->getActiveControl()->getClientSide();
329
		$options = array_merge($options, $clientSide->getOptions()->toArray());
330
		$optionString = TJavaScript::encode($options);
331
		$this->registerPradoScriptInternal('ajax');
332
		$id = $callbackHandler->getUniqueID();
333
		return "new Prado.CallbackRequest('{$id}',{$optionString})";
334
	}
335
336
	/**
337
	 * Registers callback javascript for a control.
338
	 * @param string javascript class responsible for the control being registered for callback
339
	 * @param array callback options
340
	 */
341
	public function registerCallbackControl($class, $options)
342
	{
343
		$optionString=TJavaScript::encode($options);
344
		$code="new {$class}({$optionString});";
345
		$this->_endScripts[sprintf('%08X', crc32($code))]=$code;
346
		$this->registerPradoScriptInternal('ajax');
347
348
		$params=func_get_args();
349
		$this->_page->registerCachingAction('Page.ClientScript','registerCallbackControl',$params);
350
	}
351
352
	/**
353
	 * Registers postback javascript for a control. A null class parameter will prevent
354
	 * the javascript code registration.
355
	 * @param string javascript class responsible for the control being registered for postback
356
	 * @param array postback options
357
	 */
358
	public function registerPostBackControl($class,$options)
359
	{
360
		if($class === null) {
361
			return;
362
		}
363
		if(!isset($options['FormID']) && ($form=$this->_page->getForm())!==null)
364
			$options['FormID']=$form->getClientID();
365
		$optionString=TJavaScript::encode($options);
366
		$code="new {$class}({$optionString});";
367
368
		$this->_endScripts[sprintf('%08X', crc32($code))]=$code;
369
		$this->registerPradoScriptInternal('prado');
370
371
		$params=func_get_args();
372
		$this->_page->registerCachingAction('Page.ClientScript','registerPostBackControl',$params);
373
	}
374
375
	/**
376
	 * Register a default button to panel. When the $panel is in focus and
377
	 * the 'enter' key is pressed, the $button will be clicked.
378
	 * @param TControl|string panel (or its unique ID) to register the default button action
379
	 * @param TControl|string button (or its unique ID) to trigger a postback
380
	 */
381
	public function registerDefaultButton($panel, $button)
382
	{
383
		$panelID=is_string($panel)?$panel:$panel->getUniqueID();
384
385
		if(is_string($button))
386
			$buttonID=$button;
387
		else
388
		{
389
			$button->setIsDefaultButton(true);
390
			$buttonID=$button->getUniqueID();
391
		}
392
		$options = TJavaScript::encode($this->getDefaultButtonOptions($panelID, $buttonID));
393
		$code = "new Prado.WebUI.DefaultButton($options);";
394
395
		$this->_endScripts['prado:'.$panelID]=$code;
396
		$this->registerPradoScriptInternal('prado');
397
398
		$params=array($panelID,$buttonID);
399
		$this->_page->registerCachingAction('Page.ClientScript','registerDefaultButton',$params);
400
	}
401
402
	/**
403
	 * @param string the unique ID of the container control
404
	 * @param string the unique ID of the button control
405
	 * @return array default button options.
406
	 */
407
	protected function getDefaultButtonOptions($panelID, $buttonID)
408
	{
409
		$options['ID'] = TControl::convertUniqueIdToClientId($panelID);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
410
		$options['Panel'] = TControl::convertUniqueIdToClientId($panelID);
411
		$options['Target'] = TControl::convertUniqueIdToClientId($buttonID);
412
		$options['EventTarget'] = $buttonID;
413
		$options['Event'] = 'click';
414
		return $options;
415
	}
416
417
	/**
418
	 * Registers the control to receive default focus.
419
	 * @param string the client ID of the control to receive default focus
420
	 */
421
	public function registerFocusControl($target)
422
	{
423
		$this->registerPradoScriptInternal('jquery');
424
		if($target instanceof TControl)
425
			$target=$target->getClientID();
426
		$this->_endScripts['prado:focus'] = 'jQuery(\'#'.$target.'\').focus();';
427
428
		$params=func_get_args();
429
		$this->_page->registerCachingAction('Page.ClientScript','registerFocusControl',$params);
430
	}
431
432
	/**
433
	 * Registers Prado style by library name. See "Web/Javascripts/packages.php"
434
	 * for library names.
435
	 * @param string style library name.
436
	 */
437
	public function registerPradoStyle($name)
438
	{
439
		$this->registerPradoStyleInternal($name);
440
		$params=func_get_args();
441
		$this->_page->registerCachingAction('Page.ClientScript','registerPradoStyle',$params);
442
	}
443
444
	/**
445
	 * Registers a Prado style library to be loaded.
446
	 */
447
	protected function registerPradoStyleInternal($name)
448
	{
449
		// $this->checkIfNotInRender();
450
		if(!isset($this->_registeredStyles[$name]))
451
		{
452
			$base = $this->getPradoScriptAssetUrl();
453
454
			if(self::$_styles === null)
455
			{
456
				$packageFile = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::CSS_PACKAGES_FILE;
457
				list($folders, $packages,$deps)= include($packageFile);
458
				self::$_stylesFolders = $folders;
459
				self::$_styles = $deps;
460
				self::$_stylesPackages = $packages;
461
			}
462
463
			if (isset(self::$_styles[$name]))
464
				$this->_registeredStyles[$name]=true;
465
			else
466
				throw new TInvalidOperationException('csmanager_pradostyle_invalid',$name);
467
468
			if(($packages=array_keys($this->_registeredStyles))!==array())
469
			{
470
				$packagesUrl=array();
471
				$isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug;
0 ignored issues
show
Unused Code introduced by
$isDebug is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
472
				foreach ($packages as $p)
473
				{
474
					foreach (self::$_styles[$p] as $dep)
475
					{
476
						foreach (self::$_stylesPackages[$dep] as $style)
477
						{
478
							if (!isset($this->_expandedStyles[$style]))
479
							{
480
								list($base, $subPath) = $this->getStylePackageFolder($style);
481
								list($path, $baseUrl) = $this->getPackagePathUrl($base);
0 ignored issues
show
Unused Code introduced by
The assignment to $path is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
482
483
								$this->_expandedStyles[$style] = true;
484
								// TODO minify css?
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
485
								if (!in_array($url=$baseUrl.'/'.$subPath, $packagesUrl))
486
									$packagesUrl[]=$url;
487
							}
488
						}
489
					}
490
				}
491
				foreach($packagesUrl as $url)
492
					$this->registerStyleSheetFile($url,$url);
493
			}
494
		}
495
	}
496
497
	/**
498
	 * Registers a CSS file to be rendered in the page head
499
	 *
500
	 * The CSS files in themes are registered in {@link OnPreRenderComplete onPreRenderComplete} if you want to override
501
	 * CSS styles in themes you need to register it after this event is completed.
502
	 *
503
	 * Example:
504
	 * <code>
505
	 * <?php
506
	 * class BasePage extends TPage {
507
	 *   public function onPreRenderComplete($param) {
508
	 *     parent::onPreRenderComplete($param);
509
	 *     $url = 'path/to/your/stylesheet.css';
510
	 *     $this->Page->ClientScript->registerStyleSheetFile($url, $url);
511
	 *   }
512
	 * }
513
	 * </code>
514
	 *
515
	 * @param string a unique key identifying the file
516
	 * @param string URL to the CSS file
517
	 * @param string media type of the CSS (such as 'print', 'screen', etc.). Defaults to empty, meaning the CSS applies to all media types.
518
	 */
519
	public function registerStyleSheetFile($key,$url,$media='')
520
	{
521
		if($media==='')
522
			$this->_styleSheetFiles[$key]=$url;
523
		else
524
			$this->_styleSheetFiles[$key]=array($url,$media);
525
526
		$params=func_get_args();
527
		$this->_page->registerCachingAction('Page.ClientScript','registerStyleSheetFile',$params);
528
	}
529
530
	/**
531
	 * Registers a CSS block to be rendered in the page head
532
	 * @param string a unique key identifying the CSS block
533
	 * @param string CSS block
534
	 */
535
	public function registerStyleSheet($key,$css,$media='')
536
	{
537
		$this->_styleSheets[$key]=$css;
538
539
		$params=func_get_args();
540
		$this->_page->registerCachingAction('Page.ClientScript','registerStyleSheet',$params);
541
	}
542
543
	/**
544
	 * Returns the URLs of all stylesheet files referenced on the page
545
	 * @return array List of all stylesheet urls used in the page
546
	 */
547
	public function getStyleSheetUrls()
548
	{
549
		$stylesheets = array_values(
550
			array_map(function($e) {
551
				return is_array($e) ? $e[0] : $e;
552
			}, $this->_styleSheetFiles)
553
		);
554
555
		foreach(Prado::getApplication()->getAssetManager()->getPublished() as $path=>$url)
556
			if (substr($url,strlen($url)-4)=='.css')
557
				$stylesheets[] = $url;
558
559
		$stylesheets = array_unique($stylesheets);
560
561
		return $stylesheets;
562
	}
563
564
	/**
565
	 * Returns all the stylesheet code snippets referenced on the page
566
	 * @return array List of all stylesheet snippets used in the page
567
	 */
568
	public function getStyleSheetCodes()
569
	{
570
		return array_unique(array_values($this->_styleSheets));
571
	}
572
573
	/**
574
	 * Registers a javascript file in the page head
575
	 * @param string a unique key identifying the file
576
	 * @param string URL to the javascript file
577
	 */
578
	public function registerHeadScriptFile($key,$url)
579
	{
580
		$this->checkIfNotInRender();
581
		$this->_headScriptFiles[$key]=$url;
582
583
		$params=func_get_args();
584
		$this->_page->registerCachingAction('Page.ClientScript','registerHeadScriptFile',$params);
585
	}
586
587
	/**
588
	 * Registers a javascript block in the page head.
589
	 * @param string a unique key identifying the script block
590
	 * @param string javascript block
591
	 */
592
	public function registerHeadScript($key,$script)
593
	{
594
		$this->checkIfNotInRender();
595
		$this->_headScripts[$key]=$script;
596
597
		$params=func_get_args();
598
		$this->_page->registerCachingAction('Page.ClientScript','registerHeadScript',$params);
599
	}
600
601
	/**
602
	 * Registers a javascript file to be rendered within the form
603
	 * @param string a unique key identifying the file
604
	 * @param string URL to the javascript file to be rendered
605
	 */
606
	public function registerScriptFile($key, $url)
607
	{
608
		$this->_scriptFiles[$key]=$url;
609
610
		$params=func_get_args();
611
		$this->_page->registerCachingAction('Page.ClientScript','registerScriptFile',$params);
612
	}
613
614
	/**
615
	 * Registers a javascript script block at the beginning of the form
616
	 * @param string a unique key identifying the script block
617
	 * @param string javascript block
618
	 */
619
	public function registerBeginScript($key,$script)
620
	{
621
		$this->checkIfNotInRender();
622
		$this->_beginScripts[$key]=$script;
623
624
		$params=func_get_args();
625
		$this->_page->registerCachingAction('Page.ClientScript','registerBeginScript',$params);
626
	}
627
628
	/**
629
	 * Registers a javascript script block at the end of the form
630
	 * @param string a unique key identifying the script block
631
	 * @param string javascript block
632
	 */
633
	public function registerEndScript($key,$script)
634
	{
635
		$this->_endScripts[$key]=$script;
636
637
		$params=func_get_args();
638
		$this->_page->registerCachingAction('Page.ClientScript','registerEndScript',$params);
639
	}
640
641
	/**
642
	 * Registers a hidden field to be rendered in the form.
643
	 * @param string a unique key identifying the hidden field
644
	 * @param string|array hidden field value, if the value is an array, every element
645
	 * in the array will be rendered as a hidden field value.
646
	 */
647
	public function registerHiddenField($name,$value)
648
	{
649
		$this->_hiddenFields[$name]=$value;
650
651
		$params=func_get_args();
652
		$this->_page->registerCachingAction('Page.ClientScript','registerHiddenField',$params);
653
	}
654
655
	/**
656
	 * @param string a unique key
657
	 * @return boolean whether there is a CSS file registered with the specified key
658
	 */
659
	public function isStyleSheetFileRegistered($key)
660
	{
661
		return isset($this->_styleSheetFiles[$key]);
662
	}
663
664
	/**
665
	 * @param string a unique key
666
	 * @return boolean whether there is a CSS block registered with the specified key
667
	 */
668
	public function isStyleSheetRegistered($key)
669
	{
670
		return isset($this->_styleSheets[$key]);
671
	}
672
673
	/**
674
	 * @param string a unique key
675
	 * @return boolean whether there is a head javascript file registered with the specified key
676
	 */
677
	public function isHeadScriptFileRegistered($key)
678
	{
679
		return isset($this->_headScriptFiles[$key]);
680
	}
681
682
	/**
683
	 * @param string a unique key
684
	 * @return boolean whether there is a head javascript block registered with the specified key
685
	 */
686
	public function isHeadScriptRegistered($key)
687
	{
688
		return isset($this->_headScripts[$key]);
689
	}
690
691
	/**
692
	 * @param string a unique key
693
	 * @return boolean whether there is a javascript file registered with the specified key
694
	 */
695
	public function isScriptFileRegistered($key)
696
	{
697
		return isset($this->_scriptFiles[$key]);
698
	}
699
700
	/**
701
	 * @param string a unique key
702
	 * @return boolean whether there is a beginning javascript block registered with the specified key
703
	 */
704
	public function isBeginScriptRegistered($key)
705
	{
706
		return isset($this->_beginScripts[$key]);
707
	}
708
709
	/**
710
	 * @param string a unique key
711
	 * @return boolean whether there is an ending javascript block registered with the specified key
712
	 */
713
	public function isEndScriptRegistered($key)
714
	{
715
		return isset($this->_endScripts[$key]);
716
	}
717
718
	/**
719
	 * @return boolean true if any end scripts are registered.
720
	 */
721
	public function hasEndScripts()
722
	{
723
		return count($this->_endScripts) > 0;
724
	}
725
726
	/**
727
	 * @return boolean true if any begin scripts are registered.
728
	 */
729
	public function hasBeginScripts()
730
	{
731
		return count($this->_beginScripts) > 0;
732
	}
733
734
	/**
735
	 * @param string a unique key
736
	 * @return boolean whether there is a hidden field registered with the specified key
737
	 */
738
	public function isHiddenFieldRegistered($key)
739
	{
740
		return isset($this->_hiddenFields[$key]);
741
	}
742
743
	/**
744
	 * @param THtmlWriter writer for the rendering purpose
745
	 */
746
	public function renderStyleSheetFiles($writer)
747
	{
748
		$str='';
749
		foreach($this->_styleSheetFiles as $url)
750
		{
751
			if(is_array($url))
752
				$str.="<link rel=\"stylesheet\" type=\"text/css\" media=\"{$url[1]}\" href=\"".THttpUtility::htmlEncode($url[0])."\" />\n";
753
			else
754
				$str.="<link rel=\"stylesheet\" type=\"text/css\" href=\"".THttpUtility::htmlEncode($url)."\" />\n";
755
		}
756
		$writer->write($str);
757
	}
758
759
	/**
760
	 * @param THtmlWriter writer for the rendering purpose
761
	 */
762
	public function renderStyleSheets($writer)
763
	{
764
		if(count($this->_styleSheets))
765
			$writer->write("<style type=\"text/css\">\n/*<![CDATA[*/\n".implode("\n",$this->_styleSheets)."\n/*]]>*/\n</style>\n");
766
	}
767
768
	/**
769
	 * @param THtmlWriter writer for the rendering purpose
770
	 */
771
	public function renderHeadScriptFiles($writer)
772
	{
773
		$this->renderScriptFiles($writer,$this->_headScriptFiles);
774
	}
775
776
	/**
777
	 * @param THtmlWriter writer for the rendering purpose
778
	 */
779
	public function renderHeadScripts($writer)
780
	{
781
		$writer->write(TJavaScript::renderScriptBlocks($this->_headScripts));
782
	}
783
784
	public function renderScriptFilesBegin($writer)
785
	{
786
		$this->renderAllPendingScriptFiles($writer);
787
	}
788
789
	public function renderScriptFilesEnd($writer)
790
	{
791
		$this->renderAllPendingScriptFiles($writer);
792
	}
793
794
	public function markScriptFileAsRendered($url)
795
	{
796
		$this->_renderedScriptFiles[$url] = $url;
797
		$params=func_get_args();
798
		$this->_page->registerCachingAction('Page.ClientScript','markScriptFileAsRendered',$params);
799
	}
800
801
	protected function renderScriptFiles($writer, Array $scripts)
802
	{
803
		foreach($scripts as $script)
804
		{
805
			$writer->write(TJavaScript::renderScriptFile($script));
806
			$this->markScriptFileAsRendered($script);
807
		}
808
	}
809
810
	protected function getRenderedScriptFiles()
811
	{
812
		return $this->_renderedScriptFiles;
813
	}
814
815
	/**
816
	 * @param THtmlWriter writer for the rendering purpose
817
	 */
818
	public function renderAllPendingScriptFiles($writer)
819
	{
820
		if(!empty($this->_scriptFiles))
821
		{
822
			$addedScripts = array_diff($this->_scriptFiles,$this->getRenderedScriptFiles());
823
			$this->renderScriptFiles($writer,$addedScripts);
824
		}
825
	}
826
827
	/**
828
	 * @param THtmlWriter writer for the rendering purpose
829
	 */
830
	public function renderBeginScripts($writer)
831
	{
832
		$writer->write(TJavaScript::renderScriptBlocks($this->_beginScripts));
833
	}
834
835
	/**
836
	 * @param THtmlWriter writer for the rendering purpose
837
	 */
838
	public function renderEndScripts($writer)
839
	{
840
		$writer->write(TJavaScript::renderScriptBlocks($this->_endScripts));
841
	}
842
843
	/**
844
	 * @param THtmlWriter writer for the rendering purpose
845
	 */
846
	public function renderBeginScriptsCallback($writer)
847
	{
848
		$writer->write(TJavaScript::renderScriptBlocksCallback($this->_beginScripts));
849
	}
850
851
	/**
852
	 * @param THtmlWriter writer for the rendering purpose
853
	 */
854
	public function renderEndScriptsCallback($writer)
855
	{
856
		$writer->write(TJavaScript::renderScriptBlocksCallback($this->_endScripts));
857
	}
858
859
	public function renderHiddenFieldsBegin($writer)
860
	{
861
		$this->renderHiddenFieldsInt($writer,true);
862
	}
863
864
	public function renderHiddenFieldsEnd($writer)
865
	{
866
		$this->renderHiddenFieldsInt($writer,false);
867
	}
868
869
	/**
870
	 * Flushes all pending script registrations
871
	 * @param THtmlWriter writer for the rendering purpose
872
	 * @param TControl the control forcing the flush (used only in error messages)
873
	 */
874
	public function flushScriptFiles($writer, $control=null)
875
	{
876
		if(!$this->_page->getIsCallback())
877
		{
878
			$this->_page->ensureRenderInForm($control);
879
			$this->renderAllPendingScriptFiles($writer);
880
		}
881
	}
882
883
	/**
884
	 * @param THtmlWriter writer for the rendering purpose
885
	 */
886
	protected function renderHiddenFieldsInt($writer, $initial)
887
 	{
888
		if ($initial) $this->_renderedHiddenFields = array();
889
		$str='';
890
		foreach($this->_hiddenFields as $name=>$value)
891
		{
892
			if (in_array($name,$this->_renderedHiddenFields)) continue;
893
			$id=strtr($name,':','_');
894
			if(is_array($value))
895
			{
896
				foreach($value as $v)
897
					$str.='<input type="hidden" name="'.$name.'[]" id="'.$id.'" value="'.THttpUtility::htmlEncode($value)."\" />\n";
898
			}
899
			else
900
			{
901
				$str.='<input type="hidden" name="'.$name.'" id="'.$id.'" value="'.THttpUtility::htmlEncode($value)."\" />\n";
902
			}
903
			$this->_renderedHiddenFields[] = $name;
904
		}
905
		if($str!=='')
906
			$writer->write("<div style=\"visibility:hidden;\">\n".$str."</div>\n");
907
	}
908
909
	public function getHiddenFields()
910
	{
911
		return $this->_hiddenFields;
912
	}
913
914
	/**
915
	 * Checks whether page rendering has not begun yet
916
	 */
917
	protected function checkIfNotInRender()
918
	{
919
		if ($form = $this->_page->InFormRender)
0 ignored issues
show
Bug introduced by
The property InFormRender does not seem to exist. Did you mean _inFormRender?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Unused Code introduced by
$form is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
920
			throw new \Exception('Operation invalid when page is already rendering');
921
	}
922
}
923