a36f569298a40e61a8d711aa4a4781a2098d660b
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / template / plugin / JsFunctionTemplatePlugin.class.php
1 <?php
2
3 namespace wcf\system\template\plugin;
4
5 use wcf\system\exception\SystemException;
6 use wcf\system\request\RequestHandler;
7 use wcf\system\template\TemplateEngine;
8 use wcf\system\WCF;
9 use wcf\util\StringUtil;
10
11 /**
12 * Template function plugin which generates script tags. File extension is automatically
13 * added to the script source and MUST NOT be provided.
14 *
15 * If ENABLE_DEBUG_MODE=0 then the extension is '.min.js', don't fail to provide it.
16 *
17 * The option VISITOR_USE_TINY_BUILD enables a specialized build, that is designed to
18 * provide smaller builds for visitors in order to decrease the overall payload and
19 * reduce page load time. Supporting them is optional and can be supplied by setting
20 * `hasTiny=true`, the extension is assumed to be `.tiny.min.js`.
21 *
22 * Usage:
23 * {js application='wbb' file='WBB'}
24 * http://example.com/js/WBB.js
25 *
26 * {js application='wcf' file='WCF.User' bundle='WCF.Combined'}
27 * http://example.com/wcf/js/WCF.User.js (ENABLE_DEBUG_MODE=1)
28 * http://example.com/wcf/js/WCF.Combined.min.js (ENABLE_DEBUG_MODE=0)
29 *
30 * {js application='wcf' lib='jquery'}
31 * http://example.com/wcf/js/3rdParty/jquery.js
32 *
33 * {js application='wcf' lib='jquery-ui' file='awesomeWidget'}
34 * http://example.com/wcf/js/3rdParty/jquery-ui/awesomeWidget.js
35 *
36 * {js application='wcf' file='WCF.User' bundle='WCF.Combined' hasTiny=true}
37 * http://example.com/wcf/js/WCF.User.js (ENABLE_DEBUG_MODE=1)
38 * http://example.com/wcf/js/WCF.Combined.min.js (ENABLE_DEBUG_MODE=0)
39 * http://example.com/wcf/js/WCF.Combined.tiny.min.js (ENABLE_DEBUG_MODE=0 && VISITOR_USE_TINY_BUILD=1)
40 *
41 * @author Alexander Ebert
42 * @copyright 2001-2019 WoltLab GmbH
43 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
44 * @since 3.0
45 */
46 class JsFunctionTemplatePlugin implements IFunctionTemplatePlugin
47 {
48 /**
49 * list of already included JavaScript files
50 * @var string[]
51 */
52 protected $includedFiles = [];
53
54 /**
55 * @inheritDoc
56 */
57 public function execute($tagArgs, TemplateEngine $tplObj)
58 {
59 // needed arguments: application and lib/file
60 if (empty($tagArgs['application'])) {
61 throw new SystemException("missing 'application' argument in js tag");
62 }
63 if (empty($tagArgs['file']) && empty($tagArgs['lib'])) {
64 throw new SystemException("missing 'file' or 'lib' argument in js tag");
65 }
66
67 $isJquery = false;
68 if (
69 isset($tagArgs['lib'])
70 && ($tagArgs['lib'] === 'jquery' || $tagArgs['lib'] === 'jquery-ui')
71 && empty($tagArgs['file'])
72 ) {
73 $tagArgs['bundle'] = '';
74 $isJquery = true;
75 }
76
77 $src = WCF::getPath($tagArgs['application']) . (isset($tagArgs['acp']) && $tagArgs['acp'] === 'true' ? 'acp/' : '') . 'js/';
78 if (!empty($tagArgs['bundle']) && !ENABLE_DEBUG_MODE) {
79 $src .= $tagArgs['bundle'];
80 } elseif (!empty($tagArgs['lib'])) {
81 if ($isJquery) {
82 $src .= ENABLE_DEBUG_MODE ? '3rdParty/' . $tagArgs['lib'] : 'WCF.Combined';
83 } else {
84 $src .= '3rdParty/' . $tagArgs['lib'];
85 if (!empty($tagArgs['file'])) {
86 $src .= '/' . $tagArgs['file'];
87 }
88 }
89 } else {
90 $src .= $tagArgs['file'];
91 }
92
93 if (isset($this->includedFiles[$src])) {
94 return '';
95 }
96
97 $this->includedFiles[$src] = true;
98 if (!ENABLE_DEBUG_MODE) {
99 if (
100 \defined('VISITOR_USE_TINY_BUILD')
101 && VISITOR_USE_TINY_BUILD
102 && !WCF::getUser()->userID
103 && !empty($tagArgs['hasTiny'])
104 ) {
105 $src .= '.tiny';
106 }
107
108 $src .= '.min';
109 }
110 $src .= '.js?v=' . LAST_UPDATE_TIME;
111
112 $relocate = !RequestHandler::getInstance()->isACPRequest() && (!isset($tagArgs['core']) || $tagArgs['core'] !== 'true');
113 $html = '<script' . ($relocate ? ' data-relocate="true"' : '') . ' data-cfasync="false" src="' . $src . '"></script>' . "\n";
114
115 if (isset($tagArgs['encodeJs']) && $tagArgs['encodeJs'] === 'true') {
116 $html = StringUtil::encodeJS($html);
117 }
118
119 return $html;
120 }
121 }