Passed
Push — master ( 18f234...5a0b28 )
by John
16:38 queued 11s
created
core/templates/layout.user.php 2 patches
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -5,11 +5,11 @@  discard block
 block discarded – undo
5 5
  */
6 6
 
7 7
 $getUserAvatar = static function (int $size) use ($_): string {
8
-	return \OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', [
9
-		'userId' => $_['user_uid'],
10
-		'size' => $size,
11
-		'v' => $_['userAvatarVersion']
12
-	]);
8
+    return \OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', [
9
+        'userId' => $_['user_uid'],
10
+        'size' => $size,
11
+        'v' => $_['userAvatarVersion']
12
+    ]);
13 13
 }
14 14
 
15 15
 ?><!DOCTYPE html>
@@ -18,9 +18,9 @@  discard block
 block discarded – undo
18 18
 		<meta charset="utf-8">
19 19
 		<title>
20 20
 			<?php
21
-				p(!empty($_['application'])?$_['application'].' - ':'');
22
-				p($theme->getTitle());
23
-			?>
21
+                p(!empty($_['application'])?$_['application'].' - ':'');
22
+                p($theme->getTitle());
23
+            ?>
24 24
 		</title>
25 25
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
26 26
 		<?php if ($theme->getiTunesAppId() !== '') { ?>
@@ -41,8 +41,8 @@  discard block
 block discarded – undo
41 41
 		<?php print_unescaped($_['headers']); ?>
42 42
 	</head>
43 43
 	<body id="<?php p($_['bodyid']);?>" <?php foreach ($_['enabledThemes'] as $themeId) {
44
-				p("data-theme-$themeId ");
45
-			}?> data-themes=<?php p(join(',', $_['enabledThemes'])) ?>>
44
+                p("data-theme-$themeId ");
45
+            }?> data-themes=<?php p(join(',', $_['enabledThemes'])) ?>>
46 46
 	<?php include 'layout.noscript.warning.php'; ?>
47 47
 
48 48
 		<?php foreach ($_['initialStates'] as $app => $initialState) { ?>
@@ -148,19 +148,19 @@  discard block
 block discarded – undo
148 148
 						aria-label="<?php p($l->t('Settings'));?>"
149 149
 						aria-haspopup="true" aria-controls="expanddiv" aria-expanded="false">
150 150
 						<div id="avatardiv-menu" class="avatardiv<?php if ($_['userAvatarSet']) {
151
-				print_unescaped(' avatardiv-shown');
152
-			} else {
153
-				print_unescaped('" style="display: none');
154
-			} ?>"
151
+                print_unescaped(' avatardiv-shown');
152
+            } else {
153
+                print_unescaped('" style="display: none');
154
+            } ?>"
155 155
 							 data-user="<?php p($_['user_uid']); ?>"
156 156
 							 data-displayname="<?php p($_['user_displayname']); ?>"
157 157
 			<?php
158
-			if ($_['userAvatarSet']) {
159
-				$avatar32 = $getUserAvatar(32); ?> data-avatar="<?php p($avatar32); ?>"
158
+            if ($_['userAvatarSet']) {
159
+                $avatar32 = $getUserAvatar(32); ?> data-avatar="<?php p($avatar32); ?>"
160 160
 			<?php
161
-			} ?>>
161
+            } ?>>
162 162
 							<?php
163
-							if ($_['userAvatarSet']) {?>
163
+                            if ($_['userAvatarSet']) {?>
164 164
 								<img alt="" width="32" height="32"
165 165
 								src="<?php p($avatar32);?>"
166 166
 								srcset="<?php p($getUserAvatar(64));?> 2x, <?php p($getUserAvatar(128));?> 4x"
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@  discard block
 block discarded – undo
4 4
  * @var array $_
5 5
  */
6 6
 
7
-$getUserAvatar = static function (int $size) use ($_): string {
7
+$getUserAvatar = static function(int $size) use ($_): string {
8 8
 	return \OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', [
9 9
 		'userId' => $_['user_uid'],
10 10
 		'size' => $size,
@@ -18,7 +18,7 @@  discard block
 block discarded – undo
18 18
 		<meta charset="utf-8">
19 19
 		<title>
20 20
 			<?php
21
-				p(!empty($_['application'])?$_['application'].' - ':'');
21
+				p(!empty($_['application']) ? $_['application'].' - ' : '');
22 22
 				p($theme->getTitle());
23 23
 			?>
24 24
 		</title>
@@ -28,7 +28,7 @@  discard block
 block discarded – undo
28 28
 		<?php } ?>
29 29
 		<meta name="apple-mobile-web-app-capable" content="yes">
30 30
 		<meta name="apple-mobile-web-app-status-bar-style" content="black">
31
-		<meta name="apple-mobile-web-app-title" content="<?php p((!empty($_['application']) && $_['appid'] != 'files')? $_['application']:$theme->getTitle()); ?>">
31
+		<meta name="apple-mobile-web-app-title" content="<?php p((!empty($_['application']) && $_['appid'] != 'files') ? $_['application'] : $theme->getTitle()); ?>">
32 32
 		<meta name="mobile-web-app-capable" content="yes">
33 33
 		<meta name="theme-color" content="<?php p($theme->getColorPrimary()); ?>">
34 34
 		<link rel="icon" href="<?php print_unescaped(image_path($_['appid'], 'favicon.ico')); /* IE11+ supports png */ ?>">
@@ -40,7 +40,7 @@  discard block
 block discarded – undo
40 40
 		<?php emit_script_loading_tags($_); ?>
41 41
 		<?php print_unescaped($_['headers']); ?>
42 42
 	</head>
43
-	<body id="<?php p($_['bodyid']);?>" <?php foreach ($_['enabledThemes'] as $themeId) {
43
+	<body id="<?php p($_['bodyid']); ?>" <?php foreach ($_['enabledThemes'] as $themeId) {
44 44
 				p("data-theme-$themeId ");
45 45
 			}?> data-themes=<?php p(join(',', $_['enabledThemes'])) ?>>
46 46
 	<?php include 'layout.noscript.warning.php'; ?>
@@ -61,7 +61,7 @@  discard block
 block discarded – undo
61 61
 					id="nextcloud">
62 62
 					<div class="logo logo-icon">
63 63
 						<h1 class="hidden-visually">
64
-							<?php p($theme->getName()); ?> <?php p(!empty($_['application'])?$_['application']: $l->t('Apps')); ?>
64
+							<?php p($theme->getName()); ?> <?php p(!empty($_['application']) ? $_['application'] : $l->t('Apps')); ?>
65 65
 						</h1>
66 66
 					</div>
67 67
 				</a>
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
 												<circle r="4.5" cx="21" cy="3" fill="black"/>
81 81
 											</mask>
82 82
 										</defs>
83
-										<image x="2" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" xlink:href="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>" style="<?php if ($entry['unread'] !== 0) { ?>mask: url("#hole");<?php } ?>" class="app-icon"></image>
83
+										<image x="2" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" xlink:href="<?php print_unescaped($entry['icon'].'?v='.$_['versionHash']); ?>" style="<?php if ($entry['unread'] !== 0) { ?>mask: url("#hole");<?php } ?>" class="app-icon"></image>
84 84
 										<circle class="app-icon-notification" r="3" cx="21" cy="3" fill="red"/>
85 85
 									</svg>
86 86
 								<div class="unread-counter" aria-hidden="true"><?php p($entry['unread']); ?></div>
@@ -117,7 +117,7 @@  discard block
 block discarded – undo
117 117
 													<circle r="4.5" cx="17" cy="3" fill="black"/>
118 118
 												</mask>
119 119
 											</defs>
120
-											<image x="0" y="0" width="16" height="16" preserveAspectRatio="xMinYMin meet" filter="url(#invertMenuMore-<?php p($entry['id']); ?>)" xlink:href="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>" style="<?php if ($entry['unread'] !== 0) { ?>mask: url("#hole");<?php } ?>" class="app-icon"></image>
120
+											<image x="0" y="0" width="16" height="16" preserveAspectRatio="xMinYMin meet" filter="url(#invertMenuMore-<?php p($entry['id']); ?>)" xlink:href="<?php print_unescaped($entry['icon'].'?v='.$_['versionHash']); ?>" style="<?php if ($entry['unread'] !== 0) { ?>mask: url("#hole");<?php } ?>" class="app-icon"></image>
121 121
 											<circle class="app-icon-notification" r="3" cx="17" cy="3" fill="red"/>
122 122
 										</svg>
123 123
 										<div class="unread-counter" aria-hidden="true"><?php p($entry['unread']); ?></div>
@@ -138,14 +138,14 @@  discard block
 block discarded – undo
138 138
 				<div id="contactsmenu">
139 139
 					<div class="icon-contacts menutoggle" tabindex="0" role="button"
140 140
 					aria-haspopup="true" aria-controls="contactsmenu-menu" aria-expanded="false">
141
-						<span class="hidden-visually"><?php p($l->t('Contacts'));?></span>
141
+						<span class="hidden-visually"><?php p($l->t('Contacts')); ?></span>
142 142
 					</div>
143 143
 					<div id="contactsmenu-menu" class="menu"
144
-						aria-label="<?php p($l->t('Contacts menu'));?>"></div>
144
+						aria-label="<?php p($l->t('Contacts menu')); ?>"></div>
145 145
 				</div>
146 146
 				<div id="settings">
147 147
 					<div id="expand" tabindex="0" role="button" class="menutoggle"
148
-						aria-label="<?php p($l->t('Settings'));?>"
148
+						aria-label="<?php p($l->t('Settings')); ?>"
149 149
 						aria-haspopup="true" aria-controls="expanddiv" aria-expanded="false">
150 150
 						<div id="avatardiv-menu" class="avatardiv<?php if ($_['userAvatarSet']) {
151 151
 				print_unescaped(' avatardiv-shown');
@@ -162,20 +162,20 @@  discard block
 block discarded – undo
162 162
 							<?php
163 163
 							if ($_['userAvatarSet']) {?>
164 164
 								<img alt="" width="32" height="32"
165
-								src="<?php p($avatar32);?>"
166
-								srcset="<?php p($getUserAvatar(64));?> 2x, <?php p($getUserAvatar(128));?> 4x"
165
+								src="<?php p($avatar32); ?>"
166
+								srcset="<?php p($getUserAvatar(64)); ?> 2x, <?php p($getUserAvatar(128)); ?> 4x"
167 167
 								>
168 168
 							<?php } ?>
169 169
 						</div>
170 170
 					</div>
171 171
 					<nav class="settings-menu" id="expanddiv" style="display:none;"
172
-						aria-label="<?php p($l->t('Settings menu'));?>">
172
+						aria-label="<?php p($l->t('Settings menu')); ?>">
173 173
 					<ul>
174 174
 					<?php foreach ($_['settingsnavigation'] as $entry):?>
175 175
 						<li data-id="<?php p($entry['id']); ?>">
176 176
 							<a href="<?php print_unescaped($entry['href']); ?>"
177 177
 								<?php if ($entry["active"]): ?> class="active"<?php endif; ?>>
178
-								<img alt="" src="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>">
178
+								<img alt="" src="<?php print_unescaped($entry['icon'].'?v='.$_['versionHash']); ?>">
179 179
 								<?php p($entry['name']) ?>
180 180
 							</a>
181 181
 						</li>
Please login to merge, or discard this patch.
core/routes.php 1 patch
Indentation   +81 added lines, -81 removed lines patch added patch discarded remove patch
@@ -39,94 +39,94 @@  discard block
 block discarded – undo
39 39
 /** @var Application $application */
40 40
 $application = \OC::$server->query(Application::class);
41 41
 $application->registerRoutes($this, [
42
-	'routes' => [
43
-		['name' => 'lost#email', 'url' => '/lostpassword/email', 'verb' => 'POST'],
44
-		['name' => 'lost#resetform', 'url' => '/lostpassword/reset/form/{token}/{userId}', 'verb' => 'GET'],
45
-		['name' => 'lost#setPassword', 'url' => '/lostpassword/set/{token}/{userId}', 'verb' => 'POST'],
46
-		['name' => 'ProfilePage#index', 'url' => '/u/{targetUserId}', 'verb' => 'GET'],
47
-		['name' => 'user#getDisplayNames', 'url' => '/displaynames', 'verb' => 'POST'],
48
-		['name' => 'avatar#getAvatar', 'url' => '/avatar/{userId}/{size}', 'verb' => 'GET'],
49
-		['name' => 'avatar#deleteAvatar', 'url' => '/avatar/', 'verb' => 'DELETE'],
50
-		['name' => 'avatar#postCroppedAvatar', 'url' => '/avatar/cropped', 'verb' => 'POST'],
51
-		['name' => 'avatar#getTmpAvatar', 'url' => '/avatar/tmp', 'verb' => 'GET'],
52
-		['name' => 'avatar#postAvatar', 'url' => '/avatar/', 'verb' => 'POST'],
53
-		['name' => 'GuestAvatar#getAvatar', 'url' => '/avatar/guest/{guestName}/{size}', 'verb' => 'GET'],
54
-		['name' => 'CSRFToken#index', 'url' => '/csrftoken', 'verb' => 'GET'],
55
-		['name' => 'login#tryLogin', 'url' => '/login', 'verb' => 'POST'],
56
-		['name' => 'login#confirmPassword', 'url' => '/login/confirm', 'verb' => 'POST'],
57
-		['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'],
58
-		['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'],
59
-		// Original login flow used by all clients
60
-		['name' => 'ClientFlowLogin#showAuthPickerPage', 'url' => '/login/flow', 'verb' => 'GET'],
61
-		['name' => 'ClientFlowLogin#generateAppPassword', 'url' => '/login/flow', 'verb' => 'POST'],
62
-		['name' => 'ClientFlowLogin#grantPage', 'url' => '/login/flow/grant', 'verb' => 'GET'],
63
-		['name' => 'ClientFlowLogin#apptokenRedirect', 'url' => '/login/flow/apptoken', 'verb' => 'POST'],
64
-		// NG login flow used by desktop client in case of Kerberos/fancy 2fa (smart cards for example)
65
-		['name' => 'ClientFlowLoginV2#poll', 'url' => '/login/v2/poll', 'verb' => 'POST'],
66
-		['name' => 'ClientFlowLoginV2#showAuthPickerPage', 'url' => '/login/v2/flow', 'verb' => 'GET'],
67
-		['name' => 'ClientFlowLoginV2#landing', 'url' => '/login/v2/flow/{token}', 'verb' => 'GET'],
68
-		['name' => 'ClientFlowLoginV2#grantPage', 'url' => '/login/v2/grant', 'verb' => 'GET'],
69
-		['name' => 'ClientFlowLoginV2#generateAppPassword', 'url' => '/login/v2/grant', 'verb' => 'POST'],
70
-		['name' => 'ClientFlowLoginV2#init', 'url' => '/login/v2', 'verb' => 'POST'],
71
-		['name' => 'ClientFlowLoginV2#apptokenRedirect', 'url' => '/login/v2/apptoken', 'verb' => 'POST'],
72
-		['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'],
73
-		['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'],
74
-		['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'],
75
-		['name' => 'TwoFactorChallenge#setupProviders', 'url' => 'login/setupchallenge', 'verb' => 'GET'],
76
-		['name' => 'TwoFactorChallenge#setupProvider', 'url' => 'login/setupchallenge/{providerId}', 'verb' => 'GET'],
77
-		['name' => 'TwoFactorChallenge#confirmProviderSetup', 'url' => 'login/setupchallenge/{providerId}', 'verb' => 'POST'],
78
-		['name' => 'OCJS#getConfig', 'url' => '/core/js/oc.js', 'verb' => 'GET'],
79
-		['name' => 'Preview#getPreviewByFileId', 'url' => '/core/preview', 'verb' => 'GET'],
80
-		['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'],
81
-		['name' => 'RecommendedApps#index', 'url' => '/core/apps/recommended', 'verb' => 'GET'],
82
-		['name' => 'Css#getCss', 'url' => '/css/{appName}/{fileName}', 'verb' => 'GET'],
83
-		['name' => 'Js#getJs', 'url' => '/js/{appName}/{fileName}', 'verb' => 'GET'],
84
-		['name' => 'contactsMenu#index', 'url' => '/contactsmenu/contacts', 'verb' => 'POST'],
85
-		['name' => 'contactsMenu#findOne', 'url' => '/contactsmenu/findOne', 'verb' => 'POST'],
86
-		['name' => 'WalledGarden#get', 'url' => '/204', 'verb' => 'GET'],
87
-		['name' => 'Search#search', 'url' => '/core/search', 'verb' => 'GET'],
88
-		['name' => 'Wipe#checkWipe', 'url' => '/core/wipe/check', 'verb' => 'POST'],
89
-		['name' => 'Wipe#wipeDone', 'url' => '/core/wipe/success', 'verb' => 'POST'],
42
+    'routes' => [
43
+        ['name' => 'lost#email', 'url' => '/lostpassword/email', 'verb' => 'POST'],
44
+        ['name' => 'lost#resetform', 'url' => '/lostpassword/reset/form/{token}/{userId}', 'verb' => 'GET'],
45
+        ['name' => 'lost#setPassword', 'url' => '/lostpassword/set/{token}/{userId}', 'verb' => 'POST'],
46
+        ['name' => 'ProfilePage#index', 'url' => '/u/{targetUserId}', 'verb' => 'GET'],
47
+        ['name' => 'user#getDisplayNames', 'url' => '/displaynames', 'verb' => 'POST'],
48
+        ['name' => 'avatar#getAvatar', 'url' => '/avatar/{userId}/{size}', 'verb' => 'GET'],
49
+        ['name' => 'avatar#deleteAvatar', 'url' => '/avatar/', 'verb' => 'DELETE'],
50
+        ['name' => 'avatar#postCroppedAvatar', 'url' => '/avatar/cropped', 'verb' => 'POST'],
51
+        ['name' => 'avatar#getTmpAvatar', 'url' => '/avatar/tmp', 'verb' => 'GET'],
52
+        ['name' => 'avatar#postAvatar', 'url' => '/avatar/', 'verb' => 'POST'],
53
+        ['name' => 'GuestAvatar#getAvatar', 'url' => '/avatar/guest/{guestName}/{size}', 'verb' => 'GET'],
54
+        ['name' => 'CSRFToken#index', 'url' => '/csrftoken', 'verb' => 'GET'],
55
+        ['name' => 'login#tryLogin', 'url' => '/login', 'verb' => 'POST'],
56
+        ['name' => 'login#confirmPassword', 'url' => '/login/confirm', 'verb' => 'POST'],
57
+        ['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'],
58
+        ['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'],
59
+        // Original login flow used by all clients
60
+        ['name' => 'ClientFlowLogin#showAuthPickerPage', 'url' => '/login/flow', 'verb' => 'GET'],
61
+        ['name' => 'ClientFlowLogin#generateAppPassword', 'url' => '/login/flow', 'verb' => 'POST'],
62
+        ['name' => 'ClientFlowLogin#grantPage', 'url' => '/login/flow/grant', 'verb' => 'GET'],
63
+        ['name' => 'ClientFlowLogin#apptokenRedirect', 'url' => '/login/flow/apptoken', 'verb' => 'POST'],
64
+        // NG login flow used by desktop client in case of Kerberos/fancy 2fa (smart cards for example)
65
+        ['name' => 'ClientFlowLoginV2#poll', 'url' => '/login/v2/poll', 'verb' => 'POST'],
66
+        ['name' => 'ClientFlowLoginV2#showAuthPickerPage', 'url' => '/login/v2/flow', 'verb' => 'GET'],
67
+        ['name' => 'ClientFlowLoginV2#landing', 'url' => '/login/v2/flow/{token}', 'verb' => 'GET'],
68
+        ['name' => 'ClientFlowLoginV2#grantPage', 'url' => '/login/v2/grant', 'verb' => 'GET'],
69
+        ['name' => 'ClientFlowLoginV2#generateAppPassword', 'url' => '/login/v2/grant', 'verb' => 'POST'],
70
+        ['name' => 'ClientFlowLoginV2#init', 'url' => '/login/v2', 'verb' => 'POST'],
71
+        ['name' => 'ClientFlowLoginV2#apptokenRedirect', 'url' => '/login/v2/apptoken', 'verb' => 'POST'],
72
+        ['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'],
73
+        ['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'],
74
+        ['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'],
75
+        ['name' => 'TwoFactorChallenge#setupProviders', 'url' => 'login/setupchallenge', 'verb' => 'GET'],
76
+        ['name' => 'TwoFactorChallenge#setupProvider', 'url' => 'login/setupchallenge/{providerId}', 'verb' => 'GET'],
77
+        ['name' => 'TwoFactorChallenge#confirmProviderSetup', 'url' => 'login/setupchallenge/{providerId}', 'verb' => 'POST'],
78
+        ['name' => 'OCJS#getConfig', 'url' => '/core/js/oc.js', 'verb' => 'GET'],
79
+        ['name' => 'Preview#getPreviewByFileId', 'url' => '/core/preview', 'verb' => 'GET'],
80
+        ['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'],
81
+        ['name' => 'RecommendedApps#index', 'url' => '/core/apps/recommended', 'verb' => 'GET'],
82
+        ['name' => 'Css#getCss', 'url' => '/css/{appName}/{fileName}', 'verb' => 'GET'],
83
+        ['name' => 'Js#getJs', 'url' => '/js/{appName}/{fileName}', 'verb' => 'GET'],
84
+        ['name' => 'contactsMenu#index', 'url' => '/contactsmenu/contacts', 'verb' => 'POST'],
85
+        ['name' => 'contactsMenu#findOne', 'url' => '/contactsmenu/findOne', 'verb' => 'POST'],
86
+        ['name' => 'WalledGarden#get', 'url' => '/204', 'verb' => 'GET'],
87
+        ['name' => 'Search#search', 'url' => '/core/search', 'verb' => 'GET'],
88
+        ['name' => 'Wipe#checkWipe', 'url' => '/core/wipe/check', 'verb' => 'POST'],
89
+        ['name' => 'Wipe#wipeDone', 'url' => '/core/wipe/success', 'verb' => 'POST'],
90 90
 
91
-		// Logins for passwordless auth
92
-		['name' => 'WebAuthn#startAuthentication', 'url' => 'login/webauthn/start', 'verb' => 'POST'],
93
-		['name' => 'WebAuthn#finishAuthentication', 'url' => 'login/webauthn/finish', 'verb' => 'POST'],
91
+        // Logins for passwordless auth
92
+        ['name' => 'WebAuthn#startAuthentication', 'url' => 'login/webauthn/start', 'verb' => 'POST'],
93
+        ['name' => 'WebAuthn#finishAuthentication', 'url' => 'login/webauthn/finish', 'verb' => 'POST'],
94 94
 
95
-		// Well known requests https://tools.ietf.org/html/rfc5785
96
-		['name' => 'WellKnown#handle', 'url' => '.well-known/{service}'],
97
-	],
98
-	'ocs' => [
99
-		['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
100
-		['root' => '', 'name' => 'OCS#getConfig', 'url' => '/config', 'verb' => 'GET'],
101
-		['root' => '/person', 'name' => 'OCS#personCheck', 'url' => '/check', 'verb' => 'POST'],
102
-		['root' => '/identityproof', 'name' => 'OCS#getIdentityProof', 'url' => '/key/{cloudId}', 'verb' => 'GET'],
103
-		['root' => '/core', 'name' => 'Navigation#getAppsNavigation', 'url' => '/navigation/apps', 'verb' => 'GET'],
104
-		['root' => '/core', 'name' => 'Navigation#getSettingsNavigation', 'url' => '/navigation/settings', 'verb' => 'GET'],
105
-		['root' => '/core', 'name' => 'AutoComplete#get', 'url' => '/autocomplete/get', 'verb' => 'GET'],
106
-		['root' => '/core', 'name' => 'WhatsNew#get', 'url' => '/whatsnew', 'verb' => 'GET'],
107
-		['root' => '/core', 'name' => 'WhatsNew#dismiss', 'url' => '/whatsnew', 'verb' => 'POST'],
108
-		['root' => '/core', 'name' => 'AppPassword#getAppPassword', 'url' => '/getapppassword', 'verb' => 'GET'],
109
-		['root' => '/core', 'name' => 'AppPassword#rotateAppPassword', 'url' => '/apppassword/rotate', 'verb' => 'POST'],
110
-		['root' => '/core', 'name' => 'AppPassword#deleteAppPassword', 'url' => '/apppassword', 'verb' => 'DELETE'],
95
+        // Well known requests https://tools.ietf.org/html/rfc5785
96
+        ['name' => 'WellKnown#handle', 'url' => '.well-known/{service}'],
97
+    ],
98
+    'ocs' => [
99
+        ['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
100
+        ['root' => '', 'name' => 'OCS#getConfig', 'url' => '/config', 'verb' => 'GET'],
101
+        ['root' => '/person', 'name' => 'OCS#personCheck', 'url' => '/check', 'verb' => 'POST'],
102
+        ['root' => '/identityproof', 'name' => 'OCS#getIdentityProof', 'url' => '/key/{cloudId}', 'verb' => 'GET'],
103
+        ['root' => '/core', 'name' => 'Navigation#getAppsNavigation', 'url' => '/navigation/apps', 'verb' => 'GET'],
104
+        ['root' => '/core', 'name' => 'Navigation#getSettingsNavigation', 'url' => '/navigation/settings', 'verb' => 'GET'],
105
+        ['root' => '/core', 'name' => 'AutoComplete#get', 'url' => '/autocomplete/get', 'verb' => 'GET'],
106
+        ['root' => '/core', 'name' => 'WhatsNew#get', 'url' => '/whatsnew', 'verb' => 'GET'],
107
+        ['root' => '/core', 'name' => 'WhatsNew#dismiss', 'url' => '/whatsnew', 'verb' => 'POST'],
108
+        ['root' => '/core', 'name' => 'AppPassword#getAppPassword', 'url' => '/getapppassword', 'verb' => 'GET'],
109
+        ['root' => '/core', 'name' => 'AppPassword#rotateAppPassword', 'url' => '/apppassword/rotate', 'verb' => 'POST'],
110
+        ['root' => '/core', 'name' => 'AppPassword#deleteAppPassword', 'url' => '/apppassword', 'verb' => 'DELETE'],
111 111
 
112
-		['root' => '/hovercard', 'name' => 'HoverCard#getUser', 'url' => '/v1/{userId}', 'verb' => 'GET'],
112
+        ['root' => '/hovercard', 'name' => 'HoverCard#getUser', 'url' => '/v1/{userId}', 'verb' => 'GET'],
113 113
 
114
-		['root' => '/collaboration', 'name' => 'CollaborationResources#searchCollections', 'url' => '/resources/collections/search/{filter}', 'verb' => 'GET'],
115
-		['root' => '/collaboration', 'name' => 'CollaborationResources#listCollection', 'url' => '/resources/collections/{collectionId}', 'verb' => 'GET'],
116
-		['root' => '/collaboration', 'name' => 'CollaborationResources#renameCollection', 'url' => '/resources/collections/{collectionId}', 'verb' => 'PUT'],
117
-		['root' => '/collaboration', 'name' => 'CollaborationResources#addResource', 'url' => '/resources/collections/{collectionId}', 'verb' => 'POST'],
114
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#searchCollections', 'url' => '/resources/collections/search/{filter}', 'verb' => 'GET'],
115
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#listCollection', 'url' => '/resources/collections/{collectionId}', 'verb' => 'GET'],
116
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#renameCollection', 'url' => '/resources/collections/{collectionId}', 'verb' => 'PUT'],
117
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#addResource', 'url' => '/resources/collections/{collectionId}', 'verb' => 'POST'],
118 118
 
119
-		['root' => '/collaboration', 'name' => 'CollaborationResources#removeResource', 'url' => '/resources/collections/{collectionId}', 'verb' => 'DELETE'],
120
-		['root' => '/collaboration', 'name' => 'CollaborationResources#getCollectionsByResource', 'url' => '/resources/{resourceType}/{resourceId}', 'verb' => 'GET'],
121
-		['root' => '/collaboration', 'name' => 'CollaborationResources#createCollectionOnResource', 'url' => '/resources/{baseResourceType}/{baseResourceId}', 'verb' => 'POST'],
119
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#removeResource', 'url' => '/resources/collections/{collectionId}', 'verb' => 'DELETE'],
120
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#getCollectionsByResource', 'url' => '/resources/{resourceType}/{resourceId}', 'verb' => 'GET'],
121
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#createCollectionOnResource', 'url' => '/resources/{baseResourceType}/{baseResourceId}', 'verb' => 'POST'],
122 122
 
123
-		['root' => '/profile', 'name' => 'ProfileApi#setVisibility', 'url' => '/{targetUserId}', 'verb' => 'PUT'],
123
+        ['root' => '/profile', 'name' => 'ProfileApi#setVisibility', 'url' => '/{targetUserId}', 'verb' => 'PUT'],
124 124
 
125
-		// Unified search
126
-		['root' => '/search', 'name' => 'UnifiedSearch#getProviders', 'url' => '/providers', 'verb' => 'GET'],
127
-		['root' => '/search', 'name' => 'UnifiedSearch#search', 'url' => '/providers/{providerId}/search', 'verb' => 'GET'],
125
+        // Unified search
126
+        ['root' => '/search', 'name' => 'UnifiedSearch#getProviders', 'url' => '/providers', 'verb' => 'GET'],
127
+        ['root' => '/search', 'name' => 'UnifiedSearch#search', 'url' => '/providers/{providerId}/search', 'verb' => 'GET'],
128 128
 
129
-	],
129
+    ],
130 130
 ]);
131 131
 
132 132
 // Post installation check
@@ -135,4 +135,4 @@  discard block
 block discarded – undo
135 135
 // Core ajax actions
136 136
 // Routing
137 137
 $this->create('core_ajax_update', '/core/ajax/update.php')
138
-	->actionInclude('core/ajax/update.php');
138
+    ->actionInclude('core/ajax/update.php');
Please login to merge, or discard this patch.
lib/private/legacy/OC_Template.php 1 patch
Indentation   +308 added lines, -308 removed lines patch added patch discarded remove patch
@@ -48,312 +48,312 @@
 block discarded – undo
48 48
  */
49 49
 class OC_Template extends \OC\Template\Base {
50 50
 
51
-	/** @var string */
52
-	private $renderAs; // Create a full page?
53
-
54
-	/** @var string */
55
-	private $path; // The path to the template
56
-
57
-	/** @var array */
58
-	private $headers = []; //custom headers
59
-
60
-	/** @var string */
61
-	protected $app; // app id
62
-
63
-	protected static $initTemplateEngineFirstRun = true;
64
-
65
-	/**
66
-	 * Constructor
67
-	 *
68
-	 * @param string $app app providing the template
69
-	 * @param string $name of the template file (without suffix)
70
-	 * @param string $renderAs If $renderAs is set, OC_Template will try to
71
-	 *                         produce a full page in the according layout. For
72
-	 *                         now, $renderAs can be set to "guest", "user" or
73
-	 *                         "admin".
74
-	 * @param bool $registerCall = true
75
-	 */
76
-	public function __construct($app, $name, $renderAs = TemplateResponse::RENDER_AS_BLANK, $registerCall = true) {
77
-		// Read the selected theme from the config file
78
-		self::initTemplateEngine($renderAs);
79
-
80
-		$theme = OC_Util::getTheme();
81
-
82
-		$requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : '';
83
-
84
-		$parts = explode('/', $app); // fix translation when app is something like core/lostpassword
85
-		$l10n = \OC::$server->getL10N($parts[0]);
86
-		/** @var \OCP\Defaults $themeDefaults */
87
-		$themeDefaults = \OC::$server->query(\OCP\Defaults::class);
88
-
89
-		[$path, $template] = $this->findTemplate($theme, $app, $name);
90
-
91
-		// Set the private data
92
-		$this->renderAs = $renderAs;
93
-		$this->path = $path;
94
-		$this->app = $app;
95
-
96
-		parent::__construct($template, $requestToken, $l10n, $themeDefaults);
97
-	}
98
-
99
-	/**
100
-	 * @param string $renderAs
101
-	 */
102
-	public static function initTemplateEngine($renderAs) {
103
-		if (self::$initTemplateEngineFirstRun) {
104
-
105
-			// apps that started before the template initialization can load their own scripts/styles
106
-			// so to make sure this scripts/styles here are loaded first we put all core scripts first
107
-			// check lib/public/Util.php
108
-			OC_Util::addStyle('server', null, true);
109
-
110
-			// include common nextcloud webpack bundle
111
-			Util::addScript('core', 'common');
112
-			Util::addScript('core', 'main');
113
-			Util::addTranslations('core');
114
-
115
-			if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) {
116
-				Util::addScript('core', 'files_fileinfo');
117
-				Util::addScript('core', 'files_client');
118
-				Util::addScript('core', 'merged-template-prepend');
119
-			}
120
-
121
-			// If installed and background job is set to ajax, add dedicated script
122
-			if (\OC::$server->getSystemConfig()->getValue('installed', false)
123
-				&& $renderAs !== TemplateResponse::RENDER_AS_ERROR
124
-				&& !\OCP\Util::needUpgrade()) {
125
-				if (\OC::$server->getConfig()->getAppValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
126
-					Util::addScript('core', 'backgroundjobs');
127
-				}
128
-			}
129
-
130
-			self::$initTemplateEngineFirstRun = false;
131
-		}
132
-	}
133
-
134
-
135
-	/**
136
-	 * find the template with the given name
137
-	 * @param string $name of the template file (without suffix)
138
-	 *
139
-	 * Will select the template file for the selected theme.
140
-	 * Checking all the possible locations.
141
-	 * @param string $theme
142
-	 * @param string $app
143
-	 * @return string[]
144
-	 */
145
-	protected function findTemplate($theme, $app, $name) {
146
-		// Check if it is a app template or not.
147
-		if ($app !== '') {
148
-			$dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app));
149
-		} else {
150
-			$dirs = $this->getCoreTemplateDirs($theme, OC::$SERVERROOT);
151
-		}
152
-		$locator = new \OC\Template\TemplateFileLocator($dirs);
153
-		$template = $locator->find($name);
154
-		$path = $locator->getPath();
155
-		return [$path, $template];
156
-	}
157
-
158
-	/**
159
-	 * Add a custom element to the header
160
-	 * @param string $tag tag name of the element
161
-	 * @param array $attributes array of attributes for the element
162
-	 * @param string $text the text content for the element. If $text is null then the
163
-	 * element will be written as empty element. So use "" to get a closing tag.
164
-	 */
165
-	public function addHeader($tag, $attributes, $text = null) {
166
-		$this->headers[] = [
167
-			'tag' => $tag,
168
-			'attributes' => $attributes,
169
-			'text' => $text
170
-		];
171
-	}
172
-
173
-	/**
174
-	 * Process the template
175
-	 * @return string
176
-	 *
177
-	 * This function process the template. If $this->renderAs is set, it
178
-	 * will produce a full page.
179
-	 */
180
-	public function fetchPage($additionalParams = null) {
181
-		$data = parent::fetchPage($additionalParams);
182
-
183
-		if ($this->renderAs) {
184
-			$page = new TemplateLayout($this->renderAs, $this->app);
185
-
186
-			if (is_array($additionalParams)) {
187
-				foreach ($additionalParams as $key => $value) {
188
-					$page->assign($key, $value);
189
-				}
190
-			}
191
-
192
-			// Add custom headers
193
-			$headers = '';
194
-			foreach (OC_Util::$headers as $header) {
195
-				$headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']);
196
-				if (strcasecmp($header['tag'], 'script') === 0 && in_array('src', array_map('strtolower', array_keys($header['attributes'])))) {
197
-					$headers .= ' defer';
198
-				}
199
-				foreach ($header['attributes'] as $name => $value) {
200
-					$headers .= ' '.\OCP\Util::sanitizeHTML($name).'="'.\OCP\Util::sanitizeHTML($value).'"';
201
-				}
202
-				if ($header['text'] !== null) {
203
-					$headers .= '>'.\OCP\Util::sanitizeHTML($header['text']).'</'.\OCP\Util::sanitizeHTML($header['tag']).'>';
204
-				} else {
205
-					$headers .= '/>';
206
-				}
207
-			}
208
-
209
-			$page->assign('headers', $headers);
210
-
211
-			$page->assign('content', $data);
212
-			return $page->fetchPage($additionalParams);
213
-		}
214
-
215
-		return $data;
216
-	}
217
-
218
-	/**
219
-	 * Include template
220
-	 *
221
-	 * @param string $file
222
-	 * @param array|null $additionalParams
223
-	 * @return string returns content of included template
224
-	 *
225
-	 * Includes another template. use <?php echo $this->inc('template'); ?> to
226
-	 * do this.
227
-	 */
228
-	public function inc($file, $additionalParams = null) {
229
-		return $this->load($this->path.$file.'.php', $additionalParams);
230
-	}
231
-
232
-	/**
233
-	 * Shortcut to print a simple page for users
234
-	 * @param string $application The application we render the template for
235
-	 * @param string $name Name of the template
236
-	 * @param array $parameters Parameters for the template
237
-	 * @return boolean|null
238
-	 */
239
-	public static function printUserPage($application, $name, $parameters = []) {
240
-		$content = new OC_Template($application, $name, "user");
241
-		foreach ($parameters as $key => $value) {
242
-			$content->assign($key, $value);
243
-		}
244
-		print $content->printPage();
245
-	}
246
-
247
-	/**
248
-	 * Shortcut to print a simple page for admins
249
-	 * @param string $application The application we render the template for
250
-	 * @param string $name Name of the template
251
-	 * @param array $parameters Parameters for the template
252
-	 * @return bool
253
-	 */
254
-	public static function printAdminPage($application, $name, $parameters = []) {
255
-		$content = new OC_Template($application, $name, "admin");
256
-		foreach ($parameters as $key => $value) {
257
-			$content->assign($key, $value);
258
-		}
259
-		return $content->printPage();
260
-	}
261
-
262
-	/**
263
-	 * Shortcut to print a simple page for guests
264
-	 * @param string $application The application we render the template for
265
-	 * @param string $name Name of the template
266
-	 * @param array|string $parameters Parameters for the template
267
-	 * @return bool
268
-	 */
269
-	public static function printGuestPage($application, $name, $parameters = []) {
270
-		$content = new OC_Template($application, $name, $name === 'error' ? $name : 'guest');
271
-		foreach ($parameters as $key => $value) {
272
-			$content->assign($key, $value);
273
-		}
274
-		return $content->printPage();
275
-	}
276
-
277
-	/**
278
-	 * Print a fatal error page and terminates the script
279
-	 * @param string $error_msg The error message to show
280
-	 * @param string $hint An optional hint message - needs to be properly escape
281
-	 * @param int $statusCode
282
-	 * @suppress PhanAccessMethodInternal
283
-	 */
284
-	public static function printErrorPage($error_msg, $hint = '', $statusCode = 500) {
285
-		if (\OC::$server->getAppManager()->isEnabledForUser('theming') && !\OC_App::isAppLoaded('theming')) {
286
-			\OC_App::loadApp('theming');
287
-		}
288
-
289
-
290
-		if ($error_msg === $hint) {
291
-			// If the hint is the same as the message there is no need to display it twice.
292
-			$hint = '';
293
-		}
294
-
295
-		http_response_code($statusCode);
296
-		try {
297
-			$content = new \OC_Template('', 'error', 'error', false);
298
-			$errors = [['error' => $error_msg, 'hint' => $hint]];
299
-			$content->assign('errors', $errors);
300
-			$content->printPage();
301
-		} catch (\Exception $e) {
302
-			$logger = \OC::$server->getLogger();
303
-			$logger->error("$error_msg $hint", ['app' => 'core']);
304
-			$logger->logException($e, ['app' => 'core']);
305
-
306
-			header('Content-Type: text/plain; charset=utf-8');
307
-			print("$error_msg $hint");
308
-		}
309
-		die();
310
-	}
311
-
312
-	/**
313
-	 * print error page using Exception details
314
-	 * @param Exception|Throwable $exception
315
-	 * @param int $statusCode
316
-	 * @return bool|string
317
-	 * @suppress PhanAccessMethodInternal
318
-	 */
319
-	public static function printExceptionErrorPage($exception, $statusCode = 503) {
320
-		http_response_code($statusCode);
321
-		try {
322
-			$request = \OC::$server->getRequest();
323
-			$content = new \OC_Template('', 'exception', 'error', false);
324
-			$content->assign('errorClass', get_class($exception));
325
-			$content->assign('errorMsg', $exception->getMessage());
326
-			$content->assign('errorCode', $exception->getCode());
327
-			$content->assign('file', $exception->getFile());
328
-			$content->assign('line', $exception->getLine());
329
-			$content->assign('exception', $exception);
330
-			$content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
331
-			$content->assign('remoteAddr', $request->getRemoteAddress());
332
-			$content->assign('requestID', $request->getId());
333
-			$content->printPage();
334
-		} catch (\Exception $e) {
335
-			try {
336
-				$logger = \OC::$server->getLogger();
337
-				$logger->logException($exception, ['app' => 'core']);
338
-				$logger->logException($e, ['app' => 'core']);
339
-			} catch (Throwable $e) {
340
-				// no way to log it properly - but to avoid a white page of death we send some output
341
-				header('Content-Type: text/plain; charset=utf-8');
342
-				print("Internal Server Error\n\n");
343
-				print("The server encountered an internal error and was unable to complete your request.\n");
344
-				print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
345
-				print("More details can be found in the server log.\n");
346
-
347
-				// and then throw it again to log it at least to the web server error log
348
-				throw $e;
349
-			}
350
-
351
-			header('Content-Type: text/plain; charset=utf-8');
352
-			print("Internal Server Error\n\n");
353
-			print("The server encountered an internal error and was unable to complete your request.\n");
354
-			print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
355
-			print("More details can be found in the server log.\n");
356
-		}
357
-		die();
358
-	}
51
+    /** @var string */
52
+    private $renderAs; // Create a full page?
53
+
54
+    /** @var string */
55
+    private $path; // The path to the template
56
+
57
+    /** @var array */
58
+    private $headers = []; //custom headers
59
+
60
+    /** @var string */
61
+    protected $app; // app id
62
+
63
+    protected static $initTemplateEngineFirstRun = true;
64
+
65
+    /**
66
+     * Constructor
67
+     *
68
+     * @param string $app app providing the template
69
+     * @param string $name of the template file (without suffix)
70
+     * @param string $renderAs If $renderAs is set, OC_Template will try to
71
+     *                         produce a full page in the according layout. For
72
+     *                         now, $renderAs can be set to "guest", "user" or
73
+     *                         "admin".
74
+     * @param bool $registerCall = true
75
+     */
76
+    public function __construct($app, $name, $renderAs = TemplateResponse::RENDER_AS_BLANK, $registerCall = true) {
77
+        // Read the selected theme from the config file
78
+        self::initTemplateEngine($renderAs);
79
+
80
+        $theme = OC_Util::getTheme();
81
+
82
+        $requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : '';
83
+
84
+        $parts = explode('/', $app); // fix translation when app is something like core/lostpassword
85
+        $l10n = \OC::$server->getL10N($parts[0]);
86
+        /** @var \OCP\Defaults $themeDefaults */
87
+        $themeDefaults = \OC::$server->query(\OCP\Defaults::class);
88
+
89
+        [$path, $template] = $this->findTemplate($theme, $app, $name);
90
+
91
+        // Set the private data
92
+        $this->renderAs = $renderAs;
93
+        $this->path = $path;
94
+        $this->app = $app;
95
+
96
+        parent::__construct($template, $requestToken, $l10n, $themeDefaults);
97
+    }
98
+
99
+    /**
100
+     * @param string $renderAs
101
+     */
102
+    public static function initTemplateEngine($renderAs) {
103
+        if (self::$initTemplateEngineFirstRun) {
104
+
105
+            // apps that started before the template initialization can load their own scripts/styles
106
+            // so to make sure this scripts/styles here are loaded first we put all core scripts first
107
+            // check lib/public/Util.php
108
+            OC_Util::addStyle('server', null, true);
109
+
110
+            // include common nextcloud webpack bundle
111
+            Util::addScript('core', 'common');
112
+            Util::addScript('core', 'main');
113
+            Util::addTranslations('core');
114
+
115
+            if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) {
116
+                Util::addScript('core', 'files_fileinfo');
117
+                Util::addScript('core', 'files_client');
118
+                Util::addScript('core', 'merged-template-prepend');
119
+            }
120
+
121
+            // If installed and background job is set to ajax, add dedicated script
122
+            if (\OC::$server->getSystemConfig()->getValue('installed', false)
123
+                && $renderAs !== TemplateResponse::RENDER_AS_ERROR
124
+                && !\OCP\Util::needUpgrade()) {
125
+                if (\OC::$server->getConfig()->getAppValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
126
+                    Util::addScript('core', 'backgroundjobs');
127
+                }
128
+            }
129
+
130
+            self::$initTemplateEngineFirstRun = false;
131
+        }
132
+    }
133
+
134
+
135
+    /**
136
+     * find the template with the given name
137
+     * @param string $name of the template file (without suffix)
138
+     *
139
+     * Will select the template file for the selected theme.
140
+     * Checking all the possible locations.
141
+     * @param string $theme
142
+     * @param string $app
143
+     * @return string[]
144
+     */
145
+    protected function findTemplate($theme, $app, $name) {
146
+        // Check if it is a app template or not.
147
+        if ($app !== '') {
148
+            $dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app));
149
+        } else {
150
+            $dirs = $this->getCoreTemplateDirs($theme, OC::$SERVERROOT);
151
+        }
152
+        $locator = new \OC\Template\TemplateFileLocator($dirs);
153
+        $template = $locator->find($name);
154
+        $path = $locator->getPath();
155
+        return [$path, $template];
156
+    }
157
+
158
+    /**
159
+     * Add a custom element to the header
160
+     * @param string $tag tag name of the element
161
+     * @param array $attributes array of attributes for the element
162
+     * @param string $text the text content for the element. If $text is null then the
163
+     * element will be written as empty element. So use "" to get a closing tag.
164
+     */
165
+    public function addHeader($tag, $attributes, $text = null) {
166
+        $this->headers[] = [
167
+            'tag' => $tag,
168
+            'attributes' => $attributes,
169
+            'text' => $text
170
+        ];
171
+    }
172
+
173
+    /**
174
+     * Process the template
175
+     * @return string
176
+     *
177
+     * This function process the template. If $this->renderAs is set, it
178
+     * will produce a full page.
179
+     */
180
+    public function fetchPage($additionalParams = null) {
181
+        $data = parent::fetchPage($additionalParams);
182
+
183
+        if ($this->renderAs) {
184
+            $page = new TemplateLayout($this->renderAs, $this->app);
185
+
186
+            if (is_array($additionalParams)) {
187
+                foreach ($additionalParams as $key => $value) {
188
+                    $page->assign($key, $value);
189
+                }
190
+            }
191
+
192
+            // Add custom headers
193
+            $headers = '';
194
+            foreach (OC_Util::$headers as $header) {
195
+                $headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']);
196
+                if (strcasecmp($header['tag'], 'script') === 0 && in_array('src', array_map('strtolower', array_keys($header['attributes'])))) {
197
+                    $headers .= ' defer';
198
+                }
199
+                foreach ($header['attributes'] as $name => $value) {
200
+                    $headers .= ' '.\OCP\Util::sanitizeHTML($name).'="'.\OCP\Util::sanitizeHTML($value).'"';
201
+                }
202
+                if ($header['text'] !== null) {
203
+                    $headers .= '>'.\OCP\Util::sanitizeHTML($header['text']).'</'.\OCP\Util::sanitizeHTML($header['tag']).'>';
204
+                } else {
205
+                    $headers .= '/>';
206
+                }
207
+            }
208
+
209
+            $page->assign('headers', $headers);
210
+
211
+            $page->assign('content', $data);
212
+            return $page->fetchPage($additionalParams);
213
+        }
214
+
215
+        return $data;
216
+    }
217
+
218
+    /**
219
+     * Include template
220
+     *
221
+     * @param string $file
222
+     * @param array|null $additionalParams
223
+     * @return string returns content of included template
224
+     *
225
+     * Includes another template. use <?php echo $this->inc('template'); ?> to
226
+     * do this.
227
+     */
228
+    public function inc($file, $additionalParams = null) {
229
+        return $this->load($this->path.$file.'.php', $additionalParams);
230
+    }
231
+
232
+    /**
233
+     * Shortcut to print a simple page for users
234
+     * @param string $application The application we render the template for
235
+     * @param string $name Name of the template
236
+     * @param array $parameters Parameters for the template
237
+     * @return boolean|null
238
+     */
239
+    public static function printUserPage($application, $name, $parameters = []) {
240
+        $content = new OC_Template($application, $name, "user");
241
+        foreach ($parameters as $key => $value) {
242
+            $content->assign($key, $value);
243
+        }
244
+        print $content->printPage();
245
+    }
246
+
247
+    /**
248
+     * Shortcut to print a simple page for admins
249
+     * @param string $application The application we render the template for
250
+     * @param string $name Name of the template
251
+     * @param array $parameters Parameters for the template
252
+     * @return bool
253
+     */
254
+    public static function printAdminPage($application, $name, $parameters = []) {
255
+        $content = new OC_Template($application, $name, "admin");
256
+        foreach ($parameters as $key => $value) {
257
+            $content->assign($key, $value);
258
+        }
259
+        return $content->printPage();
260
+    }
261
+
262
+    /**
263
+     * Shortcut to print a simple page for guests
264
+     * @param string $application The application we render the template for
265
+     * @param string $name Name of the template
266
+     * @param array|string $parameters Parameters for the template
267
+     * @return bool
268
+     */
269
+    public static function printGuestPage($application, $name, $parameters = []) {
270
+        $content = new OC_Template($application, $name, $name === 'error' ? $name : 'guest');
271
+        foreach ($parameters as $key => $value) {
272
+            $content->assign($key, $value);
273
+        }
274
+        return $content->printPage();
275
+    }
276
+
277
+    /**
278
+     * Print a fatal error page and terminates the script
279
+     * @param string $error_msg The error message to show
280
+     * @param string $hint An optional hint message - needs to be properly escape
281
+     * @param int $statusCode
282
+     * @suppress PhanAccessMethodInternal
283
+     */
284
+    public static function printErrorPage($error_msg, $hint = '', $statusCode = 500) {
285
+        if (\OC::$server->getAppManager()->isEnabledForUser('theming') && !\OC_App::isAppLoaded('theming')) {
286
+            \OC_App::loadApp('theming');
287
+        }
288
+
289
+
290
+        if ($error_msg === $hint) {
291
+            // If the hint is the same as the message there is no need to display it twice.
292
+            $hint = '';
293
+        }
294
+
295
+        http_response_code($statusCode);
296
+        try {
297
+            $content = new \OC_Template('', 'error', 'error', false);
298
+            $errors = [['error' => $error_msg, 'hint' => $hint]];
299
+            $content->assign('errors', $errors);
300
+            $content->printPage();
301
+        } catch (\Exception $e) {
302
+            $logger = \OC::$server->getLogger();
303
+            $logger->error("$error_msg $hint", ['app' => 'core']);
304
+            $logger->logException($e, ['app' => 'core']);
305
+
306
+            header('Content-Type: text/plain; charset=utf-8');
307
+            print("$error_msg $hint");
308
+        }
309
+        die();
310
+    }
311
+
312
+    /**
313
+     * print error page using Exception details
314
+     * @param Exception|Throwable $exception
315
+     * @param int $statusCode
316
+     * @return bool|string
317
+     * @suppress PhanAccessMethodInternal
318
+     */
319
+    public static function printExceptionErrorPage($exception, $statusCode = 503) {
320
+        http_response_code($statusCode);
321
+        try {
322
+            $request = \OC::$server->getRequest();
323
+            $content = new \OC_Template('', 'exception', 'error', false);
324
+            $content->assign('errorClass', get_class($exception));
325
+            $content->assign('errorMsg', $exception->getMessage());
326
+            $content->assign('errorCode', $exception->getCode());
327
+            $content->assign('file', $exception->getFile());
328
+            $content->assign('line', $exception->getLine());
329
+            $content->assign('exception', $exception);
330
+            $content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
331
+            $content->assign('remoteAddr', $request->getRemoteAddress());
332
+            $content->assign('requestID', $request->getId());
333
+            $content->printPage();
334
+        } catch (\Exception $e) {
335
+            try {
336
+                $logger = \OC::$server->getLogger();
337
+                $logger->logException($exception, ['app' => 'core']);
338
+                $logger->logException($e, ['app' => 'core']);
339
+            } catch (Throwable $e) {
340
+                // no way to log it properly - but to avoid a white page of death we send some output
341
+                header('Content-Type: text/plain; charset=utf-8');
342
+                print("Internal Server Error\n\n");
343
+                print("The server encountered an internal error and was unable to complete your request.\n");
344
+                print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
345
+                print("More details can be found in the server log.\n");
346
+
347
+                // and then throw it again to log it at least to the web server error log
348
+                throw $e;
349
+            }
350
+
351
+            header('Content-Type: text/plain; charset=utf-8');
352
+            print("Internal Server Error\n\n");
353
+            print("The server encountered an internal error and was unable to complete your request.\n");
354
+            print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
355
+            print("More details can be found in the server log.\n");
356
+        }
357
+        die();
358
+    }
359 359
 }
Please login to merge, or discard this patch.
lib/private/Template/SCSSCacher.php 2 patches
Indentation   +444 added lines, -444 removed lines patch added patch discarded remove patch
@@ -48,451 +48,451 @@
 block discarded – undo
48 48
 use ScssPhp\ScssPhp\OutputStyle;
49 49
 
50 50
 class SCSSCacher {
51
-	protected LoggerInterface $logger;
52
-
53
-	/** @var IAppData */
54
-	protected $appData;
55
-
56
-	/** @var IURLGenerator */
57
-	protected $urlGenerator;
58
-
59
-	/** @var IConfig */
60
-	protected $config;
61
-
62
-	/** @var \OC_Defaults */
63
-	private $defaults;
64
-
65
-	/** @var string */
66
-	protected $serverRoot;
67
-
68
-	/** @var ICache */
69
-	protected $depsCache;
70
-
71
-	/** @var null|string */
72
-	private $injectedVariables;
73
-
74
-	/** @var ICacheFactory */
75
-	private $cacheFactory;
76
-
77
-	/** @var ICache */
78
-	private $isCachedCache;
79
-
80
-	/** @var ITimeFactory */
81
-	private $timeFactory;
82
-
83
-	/** @var IMemcache */
84
-	private $lockingCache;
85
-	/** @var AppConfig */
86
-	private $appConfig;
87
-
88
-	/**
89
-	 * @param string $serverRoot
90
-	 */
91
-	public function __construct(LoggerInterface $logger,
92
-								Factory $appDataFactory,
93
-								IURLGenerator $urlGenerator,
94
-								IConfig $config,
95
-								\OC_Defaults $defaults,
96
-								$serverRoot,
97
-								ICacheFactory $cacheFactory,
98
-								ITimeFactory $timeFactory,
99
-								AppConfig $appConfig) {
100
-		$this->logger = $logger;
101
-		$this->appData = $appDataFactory->get('css');
102
-		$this->urlGenerator = $urlGenerator;
103
-		$this->config = $config;
104
-		$this->defaults = $defaults;
105
-		$this->serverRoot = $serverRoot;
106
-		$this->cacheFactory = $cacheFactory;
107
-		$this->depsCache = $cacheFactory->createDistributed('SCSS-deps-' . md5($this->urlGenerator->getBaseUrl()));
108
-		$this->isCachedCache = $cacheFactory->createDistributed('SCSS-cached-' . md5($this->urlGenerator->getBaseUrl()));
109
-		$lockingCache = $cacheFactory->createDistributed('SCSS-locks-' . md5($this->urlGenerator->getBaseUrl()));
110
-		if (!($lockingCache instanceof IMemcache)) {
111
-			$lockingCache = new NullCache();
112
-		}
113
-		$this->lockingCache = $lockingCache;
114
-		$this->timeFactory = $timeFactory;
115
-		$this->appConfig = $appConfig;
116
-	}
117
-
118
-	/**
119
-	 * Process the caching process if needed
120
-	 *
121
-	 * @param string $root Root path to the nextcloud installation
122
-	 * @param string $file
123
-	 * @param string $app The app name
124
-	 * @return boolean
125
-	 * @throws NotPermittedException
126
-	 */
127
-	public function process(string $root, string $file, string $app): bool {
128
-		$path = explode('/', $root . '/' . $file);
129
-
130
-		$fileNameSCSS = array_pop($path);
131
-		$fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
132
-
133
-		$path = implode('/', $path);
134
-		$webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);
135
-
136
-		$this->logger->debug('SCSSCacher::process ordinary check follows', ['app' => 'scss_cacher']);
137
-
138
-		try {
139
-			$folder = $this->appData->getFolder($app);
140
-		} catch (NotFoundException $e) {
141
-			// creating css appdata folder
142
-			$folder = $this->appData->newFolder($app);
143
-		}
144
-
145
-		$lockKey = $webDir . '/' . $fileNameSCSS;
146
-
147
-		if (!$this->lockingCache->add($lockKey, 'locked!', 120)) {
148
-			$this->logger->debug('SCSSCacher::process could not get lock for ' . $lockKey . ' and will wait 10 seconds for cached file to be available', ['app' => 'scss_cacher']);
149
-			$retry = 0;
150
-			sleep(1);
151
-			while ($retry < 10) {
152
-				$this->appConfig->clearCachedConfig();
153
-				$this->logger->debug('SCSSCacher::process check in while loop follows', ['app' => 'scss_cacher']);
154
-				if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $app)) {
155
-					// Inject icons vars css if any
156
-					$this->logger->debug("SCSSCacher::process cached file for app '$app' and file '$fileNameCSS' is now available after $retry s. Moving on...", ['app' => 'scss_cacher']);
157
-					return true;
158
-				}
159
-				sleep(1);
160
-				$retry++;
161
-			}
162
-			$this->logger->debug('SCSSCacher::process Giving up scss caching for ' . $lockKey, ['app' => 'scss_cacher']);
163
-			return false;
164
-		}
165
-
166
-		$this->logger->debug('SCSSCacher::process Lock acquired for ' . $lockKey, ['app' => 'scss_cacher']);
167
-		try {
168
-			$cached = $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
169
-		} catch (\Exception $e) {
170
-			$this->lockingCache->remove($lockKey);
171
-			throw $e;
172
-		}
173
-
174
-		// Cleaning lock
175
-		$this->lockingCache->remove($lockKey);
176
-		$this->logger->debug('SCSSCacher::process Lock removed for ' . $lockKey, ['app' => 'scss_cacher']);
177
-
178
-		return $cached;
179
-	}
180
-
181
-	/**
182
-	 * @param $appName
183
-	 * @param $fileName
184
-	 * @return ISimpleFile
185
-	 */
186
-	public function getCachedCSS(string $appName, string $fileName): ISimpleFile {
187
-		$folder = $this->appData->getFolder($appName);
188
-		$cachedFileName = $this->prependVersionPrefix($this->prependBaseurlPrefix($fileName), $appName);
189
-
190
-		return $folder->getFile($cachedFileName);
191
-	}
192
-
193
-	/**
194
-	 * Check if the file is cached or not
195
-	 * @param string $fileNameCSS
196
-	 * @param string $app
197
-	 * @return boolean
198
-	 */
199
-	private function isCached(string $fileNameCSS, string $app) {
200
-		$key = $this->config->getSystemValue('version') . '/' . $app . '/' . $fileNameCSS;
201
-
202
-		// If the file mtime is more recent than our cached one,
203
-		// let's consider the file is properly cached
204
-		if ($cacheValue = $this->isCachedCache->get($key)) {
205
-			if ($cacheValue > $this->timeFactory->getTime()) {
206
-				return true;
207
-			}
208
-		}
209
-		$this->logger->debug("SCSSCacher::isCached $fileNameCSS isCachedCache is expired or unset", ['app' => 'scss_cacher']);
210
-
211
-		// Creating file cache if none for further checks
212
-		try {
213
-			$folder = $this->appData->getFolder($app);
214
-		} catch (NotFoundException $e) {
215
-			$this->logger->debug("SCSSCacher::isCached app data folder for $app could not be fetched", ['app' => 'scss_cacher']);
216
-			return false;
217
-		}
218
-
219
-		// Checking if file size is coherent
220
-		// and if one of the css dependency changed
221
-		try {
222
-			$cachedFile = $folder->getFile($fileNameCSS);
223
-			if ($cachedFile->getSize() > 0) {
224
-				$depFileName = $fileNameCSS . '.deps';
225
-				$deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
226
-				if ($deps === null) {
227
-					$depFile = $folder->getFile($depFileName);
228
-					$deps = $depFile->getContent();
229
-					// Set to memcache for next run
230
-					$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
231
-				}
232
-				$deps = json_decode($deps, true);
233
-
234
-				foreach ((array) $deps as $file => $mtime) {
235
-					if (!file_exists($file) || filemtime($file) > $mtime) {
236
-						$this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached due to deps file $file", ['app' => 'scss_cacher']);
237
-						return false;
238
-					}
239
-				}
240
-
241
-				$this->logger->debug("SCSSCacher::isCached $fileNameCSS dependencies successfully cached for 5 minutes", ['app' => 'scss_cacher']);
242
-				// It would probably make sense to adjust this timeout to something higher and see if that has some effect then
243
-				$this->isCachedCache->set($key, $this->timeFactory->getTime() + 5 * 60);
244
-				return true;
245
-			}
246
-			$this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached cacheValue: $cacheValue", ['app' => 'scss_cacher']);
247
-			return false;
248
-		} catch (NotFoundException $e) {
249
-			$this->logger->debug("SCSSCacher::isCached NotFoundException " . $e->getMessage(), ['app' => 'scss_cacher']);
250
-			return false;
251
-		}
252
-	}
253
-
254
-	/**
255
-	 * Check if the variables file has changed
256
-	 * @return bool
257
-	 */
258
-	private function variablesChanged(): bool {
259
-		$cachedVariables = $this->config->getAppValue('core', 'theming.variables', '');
260
-		$injectedVariables = $this->getInjectedVariables($cachedVariables);
261
-		if ($cachedVariables !== md5($injectedVariables)) {
262
-			$this->logger->debug('SCSSCacher::variablesChanged storedVariables: ' . json_encode($this->config->getAppValue('core', 'theming.variables')) . ' currentInjectedVariables: ' . json_encode($injectedVariables), ['app' => 'scss_cacher']);
263
-			$this->config->setAppValue('core', 'theming.variables', md5($injectedVariables));
264
-			$this->resetCache();
265
-			return true;
266
-		}
267
-		return false;
268
-	}
269
-
270
-	/**
271
-	 * Cache the file with AppData
272
-	 *
273
-	 * @param string $path
274
-	 * @param string $fileNameCSS
275
-	 * @param string $fileNameSCSS
276
-	 * @param ISimpleFolder $folder
277
-	 * @param string $webDir
278
-	 * @return boolean
279
-	 * @throws NotPermittedException
280
-	 */
281
-	private function cache(string $path, string $fileNameCSS, string $fileNameSCSS, ISimpleFolder $folder, string $webDir) {
282
-		$scss = new Compiler();
283
-		$scss->setImportPaths([
284
-			$path,
285
-			$this->serverRoot . '/core/css/'
286
-		]);
287
-
288
-		// Continue after throw
289
-		if ($this->config->getSystemValue('debug')) {
290
-			// Debug mode
291
-			$scss->setOutputStyle(OutputStyle::EXPANDED);
292
-		} else {
293
-			// Compression
294
-			$scss->setOutputStyle(OutputStyle::COMPRESSED);
295
-		}
296
-
297
-		try {
298
-			$cachedfile = $folder->getFile($fileNameCSS);
299
-		} catch (NotFoundException $e) {
300
-			$cachedfile = $folder->newFile($fileNameCSS);
301
-		}
302
-
303
-		$depFileName = $fileNameCSS . '.deps';
304
-		try {
305
-			$depFile = $folder->getFile($depFileName);
306
-		} catch (NotFoundException $e) {
307
-			$depFile = $folder->newFile($depFileName);
308
-		}
309
-
310
-		// Compile
311
-		try {
312
-			$compiledScss = $scss->compile(
313
-				'$webroot: \'' . $this->getRoutePrefix() . '\';' .
314
-				$this->getInjectedVariables() .
315
-				'@import "variables.scss";' .
316
-				'@import "functions.scss";' .
317
-				'@import "' . $fileNameSCSS . '";');
318
-		} catch (\Exception $e) {
319
-			$this->logger->error($e->getMessage(), ['app' => 'scss_cacher', 'exception' => $e]);
320
-
321
-			return false;
322
-		}
323
-
324
-		// Gzip file
325
-		try {
326
-			$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
327
-		} catch (NotFoundException $e) {
328
-			$gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
329
-		}
330
-
331
-		try {
332
-			$data = $this->rebaseUrls($compiledScss, $webDir);
333
-			$cachedfile->putContent($data);
334
-			$deps = json_encode($scss->getParsedFiles());
335
-			$depFile->putContent($deps);
336
-			$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
337
-			$gzipFile->putContent(gzencode($data, 9));
338
-			$this->logger->debug('SCSSCacher::cache ' . $webDir . '/' . $fileNameSCSS . ' compiled and successfully cached', ['app' => 'scss_cacher']);
339
-
340
-			return true;
341
-		} catch (NotPermittedException $e) {
342
-			$this->logger->error('SCSSCacher::cache unable to cache: ' . $fileNameSCSS, ['app' => 'scss_cacher']);
343
-
344
-			return false;
345
-		}
346
-	}
347
-
348
-	/**
349
-	 * Reset scss cache by deleting all generated css files
350
-	 * We need to regenerate all files when variables change
351
-	 */
352
-	public function resetCache() {
353
-		$this->logger->debug('SCSSCacher::resetCache', ['app' => 'scss_cacher']);
354
-		if (!$this->lockingCache->add('resetCache', 'locked!', 120)) {
355
-			$this->logger->debug('SCSSCacher::resetCache Locked', ['app' => 'scss_cacher']);
356
-			return;
357
-		}
358
-		$this->logger->debug('SCSSCacher::resetCache Lock acquired', ['app' => 'scss_cacher']);
359
-		$this->injectedVariables = null;
360
-
361
-		// do not clear locks
362
-		$this->depsCache->clear();
363
-		$this->isCachedCache->clear();
364
-
365
-		$appDirectory = $this->appData->getDirectoryListing();
366
-		foreach ($appDirectory as $folder) {
367
-			foreach ($folder->getDirectoryListing() as $file) {
368
-				try {
369
-					$file->delete();
370
-				} catch (NotPermittedException $e) {
371
-					$this->logger->error('SCSSCacher::resetCache unable to delete file: ' . $file->getName(), ['exception' => $e, 'app' => 'scss_cacher']);
372
-				}
373
-			}
374
-		}
375
-		$this->logger->debug('SCSSCacher::resetCache css cache cleared!', ['app' => 'scss_cacher']);
376
-		$this->lockingCache->remove('resetCache');
377
-		$this->logger->debug('SCSSCacher::resetCache Locking removed', ['app' => 'scss_cacher']);
378
-	}
379
-
380
-	/**
381
-	 * @return string SCSS code for variables from OC_Defaults
382
-	 */
383
-	private function getInjectedVariables(string $cache = ''): string {
384
-		if ($this->injectedVariables !== null) {
385
-			return $this->injectedVariables;
386
-		}
387
-		$variables = '';
388
-		foreach ($this->defaults->getScssVariables() as $key => $value) {
389
-			$variables .= '$' . $key . ': ' . $value . ' !default;';
390
-		}
391
-
392
-		/*
51
+    protected LoggerInterface $logger;
52
+
53
+    /** @var IAppData */
54
+    protected $appData;
55
+
56
+    /** @var IURLGenerator */
57
+    protected $urlGenerator;
58
+
59
+    /** @var IConfig */
60
+    protected $config;
61
+
62
+    /** @var \OC_Defaults */
63
+    private $defaults;
64
+
65
+    /** @var string */
66
+    protected $serverRoot;
67
+
68
+    /** @var ICache */
69
+    protected $depsCache;
70
+
71
+    /** @var null|string */
72
+    private $injectedVariables;
73
+
74
+    /** @var ICacheFactory */
75
+    private $cacheFactory;
76
+
77
+    /** @var ICache */
78
+    private $isCachedCache;
79
+
80
+    /** @var ITimeFactory */
81
+    private $timeFactory;
82
+
83
+    /** @var IMemcache */
84
+    private $lockingCache;
85
+    /** @var AppConfig */
86
+    private $appConfig;
87
+
88
+    /**
89
+     * @param string $serverRoot
90
+     */
91
+    public function __construct(LoggerInterface $logger,
92
+                                Factory $appDataFactory,
93
+                                IURLGenerator $urlGenerator,
94
+                                IConfig $config,
95
+                                \OC_Defaults $defaults,
96
+                                $serverRoot,
97
+                                ICacheFactory $cacheFactory,
98
+                                ITimeFactory $timeFactory,
99
+                                AppConfig $appConfig) {
100
+        $this->logger = $logger;
101
+        $this->appData = $appDataFactory->get('css');
102
+        $this->urlGenerator = $urlGenerator;
103
+        $this->config = $config;
104
+        $this->defaults = $defaults;
105
+        $this->serverRoot = $serverRoot;
106
+        $this->cacheFactory = $cacheFactory;
107
+        $this->depsCache = $cacheFactory->createDistributed('SCSS-deps-' . md5($this->urlGenerator->getBaseUrl()));
108
+        $this->isCachedCache = $cacheFactory->createDistributed('SCSS-cached-' . md5($this->urlGenerator->getBaseUrl()));
109
+        $lockingCache = $cacheFactory->createDistributed('SCSS-locks-' . md5($this->urlGenerator->getBaseUrl()));
110
+        if (!($lockingCache instanceof IMemcache)) {
111
+            $lockingCache = new NullCache();
112
+        }
113
+        $this->lockingCache = $lockingCache;
114
+        $this->timeFactory = $timeFactory;
115
+        $this->appConfig = $appConfig;
116
+    }
117
+
118
+    /**
119
+     * Process the caching process if needed
120
+     *
121
+     * @param string $root Root path to the nextcloud installation
122
+     * @param string $file
123
+     * @param string $app The app name
124
+     * @return boolean
125
+     * @throws NotPermittedException
126
+     */
127
+    public function process(string $root, string $file, string $app): bool {
128
+        $path = explode('/', $root . '/' . $file);
129
+
130
+        $fileNameSCSS = array_pop($path);
131
+        $fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
132
+
133
+        $path = implode('/', $path);
134
+        $webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);
135
+
136
+        $this->logger->debug('SCSSCacher::process ordinary check follows', ['app' => 'scss_cacher']);
137
+
138
+        try {
139
+            $folder = $this->appData->getFolder($app);
140
+        } catch (NotFoundException $e) {
141
+            // creating css appdata folder
142
+            $folder = $this->appData->newFolder($app);
143
+        }
144
+
145
+        $lockKey = $webDir . '/' . $fileNameSCSS;
146
+
147
+        if (!$this->lockingCache->add($lockKey, 'locked!', 120)) {
148
+            $this->logger->debug('SCSSCacher::process could not get lock for ' . $lockKey . ' and will wait 10 seconds for cached file to be available', ['app' => 'scss_cacher']);
149
+            $retry = 0;
150
+            sleep(1);
151
+            while ($retry < 10) {
152
+                $this->appConfig->clearCachedConfig();
153
+                $this->logger->debug('SCSSCacher::process check in while loop follows', ['app' => 'scss_cacher']);
154
+                if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $app)) {
155
+                    // Inject icons vars css if any
156
+                    $this->logger->debug("SCSSCacher::process cached file for app '$app' and file '$fileNameCSS' is now available after $retry s. Moving on...", ['app' => 'scss_cacher']);
157
+                    return true;
158
+                }
159
+                sleep(1);
160
+                $retry++;
161
+            }
162
+            $this->logger->debug('SCSSCacher::process Giving up scss caching for ' . $lockKey, ['app' => 'scss_cacher']);
163
+            return false;
164
+        }
165
+
166
+        $this->logger->debug('SCSSCacher::process Lock acquired for ' . $lockKey, ['app' => 'scss_cacher']);
167
+        try {
168
+            $cached = $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
169
+        } catch (\Exception $e) {
170
+            $this->lockingCache->remove($lockKey);
171
+            throw $e;
172
+        }
173
+
174
+        // Cleaning lock
175
+        $this->lockingCache->remove($lockKey);
176
+        $this->logger->debug('SCSSCacher::process Lock removed for ' . $lockKey, ['app' => 'scss_cacher']);
177
+
178
+        return $cached;
179
+    }
180
+
181
+    /**
182
+     * @param $appName
183
+     * @param $fileName
184
+     * @return ISimpleFile
185
+     */
186
+    public function getCachedCSS(string $appName, string $fileName): ISimpleFile {
187
+        $folder = $this->appData->getFolder($appName);
188
+        $cachedFileName = $this->prependVersionPrefix($this->prependBaseurlPrefix($fileName), $appName);
189
+
190
+        return $folder->getFile($cachedFileName);
191
+    }
192
+
193
+    /**
194
+     * Check if the file is cached or not
195
+     * @param string $fileNameCSS
196
+     * @param string $app
197
+     * @return boolean
198
+     */
199
+    private function isCached(string $fileNameCSS, string $app) {
200
+        $key = $this->config->getSystemValue('version') . '/' . $app . '/' . $fileNameCSS;
201
+
202
+        // If the file mtime is more recent than our cached one,
203
+        // let's consider the file is properly cached
204
+        if ($cacheValue = $this->isCachedCache->get($key)) {
205
+            if ($cacheValue > $this->timeFactory->getTime()) {
206
+                return true;
207
+            }
208
+        }
209
+        $this->logger->debug("SCSSCacher::isCached $fileNameCSS isCachedCache is expired or unset", ['app' => 'scss_cacher']);
210
+
211
+        // Creating file cache if none for further checks
212
+        try {
213
+            $folder = $this->appData->getFolder($app);
214
+        } catch (NotFoundException $e) {
215
+            $this->logger->debug("SCSSCacher::isCached app data folder for $app could not be fetched", ['app' => 'scss_cacher']);
216
+            return false;
217
+        }
218
+
219
+        // Checking if file size is coherent
220
+        // and if one of the css dependency changed
221
+        try {
222
+            $cachedFile = $folder->getFile($fileNameCSS);
223
+            if ($cachedFile->getSize() > 0) {
224
+                $depFileName = $fileNameCSS . '.deps';
225
+                $deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
226
+                if ($deps === null) {
227
+                    $depFile = $folder->getFile($depFileName);
228
+                    $deps = $depFile->getContent();
229
+                    // Set to memcache for next run
230
+                    $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
231
+                }
232
+                $deps = json_decode($deps, true);
233
+
234
+                foreach ((array) $deps as $file => $mtime) {
235
+                    if (!file_exists($file) || filemtime($file) > $mtime) {
236
+                        $this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached due to deps file $file", ['app' => 'scss_cacher']);
237
+                        return false;
238
+                    }
239
+                }
240
+
241
+                $this->logger->debug("SCSSCacher::isCached $fileNameCSS dependencies successfully cached for 5 minutes", ['app' => 'scss_cacher']);
242
+                // It would probably make sense to adjust this timeout to something higher and see if that has some effect then
243
+                $this->isCachedCache->set($key, $this->timeFactory->getTime() + 5 * 60);
244
+                return true;
245
+            }
246
+            $this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached cacheValue: $cacheValue", ['app' => 'scss_cacher']);
247
+            return false;
248
+        } catch (NotFoundException $e) {
249
+            $this->logger->debug("SCSSCacher::isCached NotFoundException " . $e->getMessage(), ['app' => 'scss_cacher']);
250
+            return false;
251
+        }
252
+    }
253
+
254
+    /**
255
+     * Check if the variables file has changed
256
+     * @return bool
257
+     */
258
+    private function variablesChanged(): bool {
259
+        $cachedVariables = $this->config->getAppValue('core', 'theming.variables', '');
260
+        $injectedVariables = $this->getInjectedVariables($cachedVariables);
261
+        if ($cachedVariables !== md5($injectedVariables)) {
262
+            $this->logger->debug('SCSSCacher::variablesChanged storedVariables: ' . json_encode($this->config->getAppValue('core', 'theming.variables')) . ' currentInjectedVariables: ' . json_encode($injectedVariables), ['app' => 'scss_cacher']);
263
+            $this->config->setAppValue('core', 'theming.variables', md5($injectedVariables));
264
+            $this->resetCache();
265
+            return true;
266
+        }
267
+        return false;
268
+    }
269
+
270
+    /**
271
+     * Cache the file with AppData
272
+     *
273
+     * @param string $path
274
+     * @param string $fileNameCSS
275
+     * @param string $fileNameSCSS
276
+     * @param ISimpleFolder $folder
277
+     * @param string $webDir
278
+     * @return boolean
279
+     * @throws NotPermittedException
280
+     */
281
+    private function cache(string $path, string $fileNameCSS, string $fileNameSCSS, ISimpleFolder $folder, string $webDir) {
282
+        $scss = new Compiler();
283
+        $scss->setImportPaths([
284
+            $path,
285
+            $this->serverRoot . '/core/css/'
286
+        ]);
287
+
288
+        // Continue after throw
289
+        if ($this->config->getSystemValue('debug')) {
290
+            // Debug mode
291
+            $scss->setOutputStyle(OutputStyle::EXPANDED);
292
+        } else {
293
+            // Compression
294
+            $scss->setOutputStyle(OutputStyle::COMPRESSED);
295
+        }
296
+
297
+        try {
298
+            $cachedfile = $folder->getFile($fileNameCSS);
299
+        } catch (NotFoundException $e) {
300
+            $cachedfile = $folder->newFile($fileNameCSS);
301
+        }
302
+
303
+        $depFileName = $fileNameCSS . '.deps';
304
+        try {
305
+            $depFile = $folder->getFile($depFileName);
306
+        } catch (NotFoundException $e) {
307
+            $depFile = $folder->newFile($depFileName);
308
+        }
309
+
310
+        // Compile
311
+        try {
312
+            $compiledScss = $scss->compile(
313
+                '$webroot: \'' . $this->getRoutePrefix() . '\';' .
314
+                $this->getInjectedVariables() .
315
+                '@import "variables.scss";' .
316
+                '@import "functions.scss";' .
317
+                '@import "' . $fileNameSCSS . '";');
318
+        } catch (\Exception $e) {
319
+            $this->logger->error($e->getMessage(), ['app' => 'scss_cacher', 'exception' => $e]);
320
+
321
+            return false;
322
+        }
323
+
324
+        // Gzip file
325
+        try {
326
+            $gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
327
+        } catch (NotFoundException $e) {
328
+            $gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
329
+        }
330
+
331
+        try {
332
+            $data = $this->rebaseUrls($compiledScss, $webDir);
333
+            $cachedfile->putContent($data);
334
+            $deps = json_encode($scss->getParsedFiles());
335
+            $depFile->putContent($deps);
336
+            $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
337
+            $gzipFile->putContent(gzencode($data, 9));
338
+            $this->logger->debug('SCSSCacher::cache ' . $webDir . '/' . $fileNameSCSS . ' compiled and successfully cached', ['app' => 'scss_cacher']);
339
+
340
+            return true;
341
+        } catch (NotPermittedException $e) {
342
+            $this->logger->error('SCSSCacher::cache unable to cache: ' . $fileNameSCSS, ['app' => 'scss_cacher']);
343
+
344
+            return false;
345
+        }
346
+    }
347
+
348
+    /**
349
+     * Reset scss cache by deleting all generated css files
350
+     * We need to regenerate all files when variables change
351
+     */
352
+    public function resetCache() {
353
+        $this->logger->debug('SCSSCacher::resetCache', ['app' => 'scss_cacher']);
354
+        if (!$this->lockingCache->add('resetCache', 'locked!', 120)) {
355
+            $this->logger->debug('SCSSCacher::resetCache Locked', ['app' => 'scss_cacher']);
356
+            return;
357
+        }
358
+        $this->logger->debug('SCSSCacher::resetCache Lock acquired', ['app' => 'scss_cacher']);
359
+        $this->injectedVariables = null;
360
+
361
+        // do not clear locks
362
+        $this->depsCache->clear();
363
+        $this->isCachedCache->clear();
364
+
365
+        $appDirectory = $this->appData->getDirectoryListing();
366
+        foreach ($appDirectory as $folder) {
367
+            foreach ($folder->getDirectoryListing() as $file) {
368
+                try {
369
+                    $file->delete();
370
+                } catch (NotPermittedException $e) {
371
+                    $this->logger->error('SCSSCacher::resetCache unable to delete file: ' . $file->getName(), ['exception' => $e, 'app' => 'scss_cacher']);
372
+                }
373
+            }
374
+        }
375
+        $this->logger->debug('SCSSCacher::resetCache css cache cleared!', ['app' => 'scss_cacher']);
376
+        $this->lockingCache->remove('resetCache');
377
+        $this->logger->debug('SCSSCacher::resetCache Locking removed', ['app' => 'scss_cacher']);
378
+    }
379
+
380
+    /**
381
+     * @return string SCSS code for variables from OC_Defaults
382
+     */
383
+    private function getInjectedVariables(string $cache = ''): string {
384
+        if ($this->injectedVariables !== null) {
385
+            return $this->injectedVariables;
386
+        }
387
+        $variables = '';
388
+        foreach ($this->defaults->getScssVariables() as $key => $value) {
389
+            $variables .= '$' . $key . ': ' . $value . ' !default;';
390
+        }
391
+
392
+        /*
393 393
 		 * If we are trying to return the same variables as that are cached
394 394
 		 * Then there is no need to do the compile step
395 395
 		 */
396
-		if ($cache === md5($variables)) {
397
-			$this->injectedVariables = $variables;
398
-			return $variables;
399
-		}
400
-
401
-		// check for valid variables / otherwise fall back to defaults
402
-		try {
403
-			$scss = new Compiler();
404
-			$scss->compile($variables);
405
-			$this->injectedVariables = $variables;
406
-		} catch (\Exception $e) {
407
-			$this->logger->error($e->getMessage(), ['exception' => $e, 'app' => 'scss_cacher']);
408
-		}
409
-
410
-		return $variables;
411
-	}
412
-
413
-	/**
414
-	 * Add the correct uri prefix to make uri valid again
415
-	 * @param string $css
416
-	 * @param string $webDir
417
-	 * @return string
418
-	 */
419
-	private function rebaseUrls(string $css, string $webDir): string {
420
-		$re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
421
-		$subst = 'url(\'' . $webDir . '/$1\')';
422
-
423
-		return preg_replace($re, $subst, $css);
424
-	}
425
-
426
-	/**
427
-	 * Return the cached css file uri
428
-	 * @param string $appName the app name
429
-	 * @param string $fileName
430
-	 * @return string
431
-	 */
432
-	public function getCachedSCSS(string $appName, string $fileName): string {
433
-		$tmpfileLoc = explode('/', $fileName);
434
-		$fileName = array_pop($tmpfileLoc);
435
-		$fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName);
436
-
437
-		return substr($this->urlGenerator->linkToRoute('core.Css.getCss', [
438
-			'fileName' => $fileName,
439
-			'appName' => $appName,
440
-			'v' => $this->config->getAppValue('core', 'theming.variables', '0')
441
-		]), \strlen(\OC::$WEBROOT) + 1);
442
-	}
443
-
444
-	/**
445
-	 * Prepend hashed base url to the css file
446
-	 * @param string $cssFile
447
-	 * @return string
448
-	 */
449
-	private function prependBaseurlPrefix(string $cssFile): string {
450
-		return substr(md5($this->urlGenerator->getBaseUrl() . $this->getRoutePrefix()), 0, 4) . '-' . $cssFile;
451
-	}
452
-
453
-	private function getRoutePrefix() {
454
-		$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
455
-		$prefix = \OC::$WEBROOT . '/index.php';
456
-		if ($frontControllerActive) {
457
-			$prefix = \OC::$WEBROOT;
458
-		}
459
-		return $prefix;
460
-	}
461
-
462
-	/**
463
-	 * Prepend hashed app version hash
464
-	 * @param string $cssFile
465
-	 * @param string $appId
466
-	 * @return string
467
-	 */
468
-	private function prependVersionPrefix(string $cssFile, string $appId): string {
469
-		$appVersion = \OC_App::getAppVersion($appId);
470
-		if ($appVersion !== '0') {
471
-			return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
472
-		}
473
-		$coreVersion = \OC_Util::getVersionString();
474
-
475
-		return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
476
-	}
477
-
478
-	/**
479
-	 * Get WebDir root
480
-	 * @param string $path the css file path
481
-	 * @param string $appName the app name
482
-	 * @param string $serverRoot the server root path
483
-	 * @param string $webRoot the nextcloud installation root path
484
-	 * @return string the webDir
485
-	 */
486
-	private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string {
487
-		// Detect if path is within server root AND if path is within an app path
488
-		if (strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
489
-			// Get the file path within the app directory
490
-			$appDirectoryPath = explode($appName, $path)[1];
491
-			// Remove the webroot
492
-
493
-			return str_replace($webRoot, '', $appWebPath . $appDirectoryPath);
494
-		}
495
-
496
-		return $webRoot . substr($path, strlen($serverRoot));
497
-	}
396
+        if ($cache === md5($variables)) {
397
+            $this->injectedVariables = $variables;
398
+            return $variables;
399
+        }
400
+
401
+        // check for valid variables / otherwise fall back to defaults
402
+        try {
403
+            $scss = new Compiler();
404
+            $scss->compile($variables);
405
+            $this->injectedVariables = $variables;
406
+        } catch (\Exception $e) {
407
+            $this->logger->error($e->getMessage(), ['exception' => $e, 'app' => 'scss_cacher']);
408
+        }
409
+
410
+        return $variables;
411
+    }
412
+
413
+    /**
414
+     * Add the correct uri prefix to make uri valid again
415
+     * @param string $css
416
+     * @param string $webDir
417
+     * @return string
418
+     */
419
+    private function rebaseUrls(string $css, string $webDir): string {
420
+        $re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
421
+        $subst = 'url(\'' . $webDir . '/$1\')';
422
+
423
+        return preg_replace($re, $subst, $css);
424
+    }
425
+
426
+    /**
427
+     * Return the cached css file uri
428
+     * @param string $appName the app name
429
+     * @param string $fileName
430
+     * @return string
431
+     */
432
+    public function getCachedSCSS(string $appName, string $fileName): string {
433
+        $tmpfileLoc = explode('/', $fileName);
434
+        $fileName = array_pop($tmpfileLoc);
435
+        $fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName);
436
+
437
+        return substr($this->urlGenerator->linkToRoute('core.Css.getCss', [
438
+            'fileName' => $fileName,
439
+            'appName' => $appName,
440
+            'v' => $this->config->getAppValue('core', 'theming.variables', '0')
441
+        ]), \strlen(\OC::$WEBROOT) + 1);
442
+    }
443
+
444
+    /**
445
+     * Prepend hashed base url to the css file
446
+     * @param string $cssFile
447
+     * @return string
448
+     */
449
+    private function prependBaseurlPrefix(string $cssFile): string {
450
+        return substr(md5($this->urlGenerator->getBaseUrl() . $this->getRoutePrefix()), 0, 4) . '-' . $cssFile;
451
+    }
452
+
453
+    private function getRoutePrefix() {
454
+        $frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
455
+        $prefix = \OC::$WEBROOT . '/index.php';
456
+        if ($frontControllerActive) {
457
+            $prefix = \OC::$WEBROOT;
458
+        }
459
+        return $prefix;
460
+    }
461
+
462
+    /**
463
+     * Prepend hashed app version hash
464
+     * @param string $cssFile
465
+     * @param string $appId
466
+     * @return string
467
+     */
468
+    private function prependVersionPrefix(string $cssFile, string $appId): string {
469
+        $appVersion = \OC_App::getAppVersion($appId);
470
+        if ($appVersion !== '0') {
471
+            return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
472
+        }
473
+        $coreVersion = \OC_Util::getVersionString();
474
+
475
+        return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
476
+    }
477
+
478
+    /**
479
+     * Get WebDir root
480
+     * @param string $path the css file path
481
+     * @param string $appName the app name
482
+     * @param string $serverRoot the server root path
483
+     * @param string $webRoot the nextcloud installation root path
484
+     * @return string the webDir
485
+     */
486
+    private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string {
487
+        // Detect if path is within server root AND if path is within an app path
488
+        if (strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
489
+            // Get the file path within the app directory
490
+            $appDirectoryPath = explode($appName, $path)[1];
491
+            // Remove the webroot
492
+
493
+            return str_replace($webRoot, '', $appWebPath . $appDirectoryPath);
494
+        }
495
+
496
+        return $webRoot . substr($path, strlen($serverRoot));
497
+    }
498 498
 }
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -104,9 +104,9 @@  discard block
 block discarded – undo
104 104
 		$this->defaults = $defaults;
105 105
 		$this->serverRoot = $serverRoot;
106 106
 		$this->cacheFactory = $cacheFactory;
107
-		$this->depsCache = $cacheFactory->createDistributed('SCSS-deps-' . md5($this->urlGenerator->getBaseUrl()));
108
-		$this->isCachedCache = $cacheFactory->createDistributed('SCSS-cached-' . md5($this->urlGenerator->getBaseUrl()));
109
-		$lockingCache = $cacheFactory->createDistributed('SCSS-locks-' . md5($this->urlGenerator->getBaseUrl()));
107
+		$this->depsCache = $cacheFactory->createDistributed('SCSS-deps-'.md5($this->urlGenerator->getBaseUrl()));
108
+		$this->isCachedCache = $cacheFactory->createDistributed('SCSS-cached-'.md5($this->urlGenerator->getBaseUrl()));
109
+		$lockingCache = $cacheFactory->createDistributed('SCSS-locks-'.md5($this->urlGenerator->getBaseUrl()));
110 110
 		if (!($lockingCache instanceof IMemcache)) {
111 111
 			$lockingCache = new NullCache();
112 112
 		}
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
 	 * @throws NotPermittedException
126 126
 	 */
127 127
 	public function process(string $root, string $file, string $app): bool {
128
-		$path = explode('/', $root . '/' . $file);
128
+		$path = explode('/', $root.'/'.$file);
129 129
 
130 130
 		$fileNameSCSS = array_pop($path);
131 131
 		$fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
@@ -142,10 +142,10 @@  discard block
 block discarded – undo
142 142
 			$folder = $this->appData->newFolder($app);
143 143
 		}
144 144
 
145
-		$lockKey = $webDir . '/' . $fileNameSCSS;
145
+		$lockKey = $webDir.'/'.$fileNameSCSS;
146 146
 
147 147
 		if (!$this->lockingCache->add($lockKey, 'locked!', 120)) {
148
-			$this->logger->debug('SCSSCacher::process could not get lock for ' . $lockKey . ' and will wait 10 seconds for cached file to be available', ['app' => 'scss_cacher']);
148
+			$this->logger->debug('SCSSCacher::process could not get lock for '.$lockKey.' and will wait 10 seconds for cached file to be available', ['app' => 'scss_cacher']);
149 149
 			$retry = 0;
150 150
 			sleep(1);
151 151
 			while ($retry < 10) {
@@ -159,11 +159,11 @@  discard block
 block discarded – undo
159 159
 				sleep(1);
160 160
 				$retry++;
161 161
 			}
162
-			$this->logger->debug('SCSSCacher::process Giving up scss caching for ' . $lockKey, ['app' => 'scss_cacher']);
162
+			$this->logger->debug('SCSSCacher::process Giving up scss caching for '.$lockKey, ['app' => 'scss_cacher']);
163 163
 			return false;
164 164
 		}
165 165
 
166
-		$this->logger->debug('SCSSCacher::process Lock acquired for ' . $lockKey, ['app' => 'scss_cacher']);
166
+		$this->logger->debug('SCSSCacher::process Lock acquired for '.$lockKey, ['app' => 'scss_cacher']);
167 167
 		try {
168 168
 			$cached = $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
169 169
 		} catch (\Exception $e) {
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
 
174 174
 		// Cleaning lock
175 175
 		$this->lockingCache->remove($lockKey);
176
-		$this->logger->debug('SCSSCacher::process Lock removed for ' . $lockKey, ['app' => 'scss_cacher']);
176
+		$this->logger->debug('SCSSCacher::process Lock removed for '.$lockKey, ['app' => 'scss_cacher']);
177 177
 
178 178
 		return $cached;
179 179
 	}
@@ -197,7 +197,7 @@  discard block
 block discarded – undo
197 197
 	 * @return boolean
198 198
 	 */
199 199
 	private function isCached(string $fileNameCSS, string $app) {
200
-		$key = $this->config->getSystemValue('version') . '/' . $app . '/' . $fileNameCSS;
200
+		$key = $this->config->getSystemValue('version').'/'.$app.'/'.$fileNameCSS;
201 201
 
202 202
 		// If the file mtime is more recent than our cached one,
203 203
 		// let's consider the file is properly cached
@@ -221,13 +221,13 @@  discard block
 block discarded – undo
221 221
 		try {
222 222
 			$cachedFile = $folder->getFile($fileNameCSS);
223 223
 			if ($cachedFile->getSize() > 0) {
224
-				$depFileName = $fileNameCSS . '.deps';
225
-				$deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
224
+				$depFileName = $fileNameCSS.'.deps';
225
+				$deps = $this->depsCache->get($folder->getName().'-'.$depFileName);
226 226
 				if ($deps === null) {
227 227
 					$depFile = $folder->getFile($depFileName);
228 228
 					$deps = $depFile->getContent();
229 229
 					// Set to memcache for next run
230
-					$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
230
+					$this->depsCache->set($folder->getName().'-'.$depFileName, $deps);
231 231
 				}
232 232
 				$deps = json_decode($deps, true);
233 233
 
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
 			$this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached cacheValue: $cacheValue", ['app' => 'scss_cacher']);
247 247
 			return false;
248 248
 		} catch (NotFoundException $e) {
249
-			$this->logger->debug("SCSSCacher::isCached NotFoundException " . $e->getMessage(), ['app' => 'scss_cacher']);
249
+			$this->logger->debug("SCSSCacher::isCached NotFoundException ".$e->getMessage(), ['app' => 'scss_cacher']);
250 250
 			return false;
251 251
 		}
252 252
 	}
@@ -259,7 +259,7 @@  discard block
 block discarded – undo
259 259
 		$cachedVariables = $this->config->getAppValue('core', 'theming.variables', '');
260 260
 		$injectedVariables = $this->getInjectedVariables($cachedVariables);
261 261
 		if ($cachedVariables !== md5($injectedVariables)) {
262
-			$this->logger->debug('SCSSCacher::variablesChanged storedVariables: ' . json_encode($this->config->getAppValue('core', 'theming.variables')) . ' currentInjectedVariables: ' . json_encode($injectedVariables), ['app' => 'scss_cacher']);
262
+			$this->logger->debug('SCSSCacher::variablesChanged storedVariables: '.json_encode($this->config->getAppValue('core', 'theming.variables')).' currentInjectedVariables: '.json_encode($injectedVariables), ['app' => 'scss_cacher']);
263 263
 			$this->config->setAppValue('core', 'theming.variables', md5($injectedVariables));
264 264
 			$this->resetCache();
265 265
 			return true;
@@ -282,7 +282,7 @@  discard block
 block discarded – undo
282 282
 		$scss = new Compiler();
283 283
 		$scss->setImportPaths([
284 284
 			$path,
285
-			$this->serverRoot . '/core/css/'
285
+			$this->serverRoot.'/core/css/'
286 286
 		]);
287 287
 
288 288
 		// Continue after throw
@@ -300,7 +300,7 @@  discard block
 block discarded – undo
300 300
 			$cachedfile = $folder->newFile($fileNameCSS);
301 301
 		}
302 302
 
303
-		$depFileName = $fileNameCSS . '.deps';
303
+		$depFileName = $fileNameCSS.'.deps';
304 304
 		try {
305 305
 			$depFile = $folder->getFile($depFileName);
306 306
 		} catch (NotFoundException $e) {
@@ -310,11 +310,11 @@  discard block
 block discarded – undo
310 310
 		// Compile
311 311
 		try {
312 312
 			$compiledScss = $scss->compile(
313
-				'$webroot: \'' . $this->getRoutePrefix() . '\';' .
314
-				$this->getInjectedVariables() .
315
-				'@import "variables.scss";' .
316
-				'@import "functions.scss";' .
317
-				'@import "' . $fileNameSCSS . '";');
313
+				'$webroot: \''.$this->getRoutePrefix().'\';'.
314
+				$this->getInjectedVariables().
315
+				'@import "variables.scss";'.
316
+				'@import "functions.scss";'.
317
+				'@import "'.$fileNameSCSS.'";');
318 318
 		} catch (\Exception $e) {
319 319
 			$this->logger->error($e->getMessage(), ['app' => 'scss_cacher', 'exception' => $e]);
320 320
 
@@ -323,9 +323,9 @@  discard block
 block discarded – undo
323 323
 
324 324
 		// Gzip file
325 325
 		try {
326
-			$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
326
+			$gzipFile = $folder->getFile($fileNameCSS.'.gzip'); # Safari doesn't like .gz
327 327
 		} catch (NotFoundException $e) {
328
-			$gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
328
+			$gzipFile = $folder->newFile($fileNameCSS.'.gzip'); # Safari doesn't like .gz
329 329
 		}
330 330
 
331 331
 		try {
@@ -333,13 +333,13 @@  discard block
 block discarded – undo
333 333
 			$cachedfile->putContent($data);
334 334
 			$deps = json_encode($scss->getParsedFiles());
335 335
 			$depFile->putContent($deps);
336
-			$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
336
+			$this->depsCache->set($folder->getName().'-'.$depFileName, $deps);
337 337
 			$gzipFile->putContent(gzencode($data, 9));
338
-			$this->logger->debug('SCSSCacher::cache ' . $webDir . '/' . $fileNameSCSS . ' compiled and successfully cached', ['app' => 'scss_cacher']);
338
+			$this->logger->debug('SCSSCacher::cache '.$webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'scss_cacher']);
339 339
 
340 340
 			return true;
341 341
 		} catch (NotPermittedException $e) {
342
-			$this->logger->error('SCSSCacher::cache unable to cache: ' . $fileNameSCSS, ['app' => 'scss_cacher']);
342
+			$this->logger->error('SCSSCacher::cache unable to cache: '.$fileNameSCSS, ['app' => 'scss_cacher']);
343 343
 
344 344
 			return false;
345 345
 		}
@@ -368,7 +368,7 @@  discard block
 block discarded – undo
368 368
 				try {
369 369
 					$file->delete();
370 370
 				} catch (NotPermittedException $e) {
371
-					$this->logger->error('SCSSCacher::resetCache unable to delete file: ' . $file->getName(), ['exception' => $e, 'app' => 'scss_cacher']);
371
+					$this->logger->error('SCSSCacher::resetCache unable to delete file: '.$file->getName(), ['exception' => $e, 'app' => 'scss_cacher']);
372 372
 				}
373 373
 			}
374 374
 		}
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
 		}
387 387
 		$variables = '';
388 388
 		foreach ($this->defaults->getScssVariables() as $key => $value) {
389
-			$variables .= '$' . $key . ': ' . $value . ' !default;';
389
+			$variables .= '$'.$key.': '.$value.' !default;';
390 390
 		}
391 391
 
392 392
 		/*
@@ -418,7 +418,7 @@  discard block
 block discarded – undo
418 418
 	 */
419 419
 	private function rebaseUrls(string $css, string $webDir): string {
420 420
 		$re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
421
-		$subst = 'url(\'' . $webDir . '/$1\')';
421
+		$subst = 'url(\''.$webDir.'/$1\')';
422 422
 
423 423
 		return preg_replace($re, $subst, $css);
424 424
 	}
@@ -447,12 +447,12 @@  discard block
 block discarded – undo
447 447
 	 * @return string
448 448
 	 */
449 449
 	private function prependBaseurlPrefix(string $cssFile): string {
450
-		return substr(md5($this->urlGenerator->getBaseUrl() . $this->getRoutePrefix()), 0, 4) . '-' . $cssFile;
450
+		return substr(md5($this->urlGenerator->getBaseUrl().$this->getRoutePrefix()), 0, 4).'-'.$cssFile;
451 451
 	}
452 452
 
453 453
 	private function getRoutePrefix() {
454 454
 		$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
455
-		$prefix = \OC::$WEBROOT . '/index.php';
455
+		$prefix = \OC::$WEBROOT.'/index.php';
456 456
 		if ($frontControllerActive) {
457 457
 			$prefix = \OC::$WEBROOT;
458 458
 		}
@@ -468,11 +468,11 @@  discard block
 block discarded – undo
468 468
 	private function prependVersionPrefix(string $cssFile, string $appId): string {
469 469
 		$appVersion = \OC_App::getAppVersion($appId);
470 470
 		if ($appVersion !== '0') {
471
-			return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
471
+			return substr(md5($appVersion), 0, 4).'-'.$cssFile;
472 472
 		}
473 473
 		$coreVersion = \OC_Util::getVersionString();
474 474
 
475
-		return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
475
+		return substr(md5($coreVersion), 0, 4).'-'.$cssFile;
476 476
 	}
477 477
 
478 478
 	/**
@@ -490,9 +490,9 @@  discard block
 block discarded – undo
490 490
 			$appDirectoryPath = explode($appName, $path)[1];
491 491
 			// Remove the webroot
492 492
 
493
-			return str_replace($webRoot, '', $appWebPath . $appDirectoryPath);
493
+			return str_replace($webRoot, '', $appWebPath.$appDirectoryPath);
494 494
 		}
495 495
 
496
-		return $webRoot . substr($path, strlen($serverRoot));
496
+		return $webRoot.substr($path, strlen($serverRoot));
497 497
 	}
498 498
 }
Please login to merge, or discard this patch.