1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | /** |
||||
6 | * Saito - The Threaded Web Forum |
||||
7 | * |
||||
8 | * @copyright Copyright (c) the Saito Project Developers |
||||
9 | * @link https://github.com/Schlaefer/Saito |
||||
10 | * @license http://opensource.org/licenses/MIT |
||||
11 | */ |
||||
12 | |||||
13 | namespace App\Controller; |
||||
14 | |||||
15 | use App\Controller\Component\AuthUserComponent; |
||||
16 | use App\Controller\Component\JsDataComponent; |
||||
0 ignored issues
–
show
|
|||||
17 | use App\Controller\Component\RefererComponent; |
||||
18 | use App\Controller\Component\SaitoEmailComponent; |
||||
19 | use App\Controller\Component\SlidetabsComponent; |
||||
20 | use App\Controller\Component\ThemesComponent; |
||||
21 | use App\Controller\Component\TitleComponent; |
||||
22 | use App\Model\Table\UsersTable; |
||||
23 | use Authentication\Controller\Component\AuthenticationComponent; |
||||
24 | use Cake\Controller\Controller; |
||||
25 | use Cake\Core\Configure; |
||||
26 | use Cake\Core\InstanceConfigTrait; |
||||
27 | use Cake\Event\Event; |
||||
28 | use Cake\Http\Response; |
||||
29 | use Cake\I18n\I18n; |
||||
30 | use Cake\ORM\TableRegistry; |
||||
31 | use Saito\App\Registry; |
||||
32 | use Saito\App\SettingsImmutable; |
||||
33 | use Saito\Event\SaitoEventManager; |
||||
34 | use Saito\User\CurrentUser\CurrentUserInterface; |
||||
35 | use Stopwatch\Lib\Stopwatch; |
||||
36 | |||||
37 | /** |
||||
38 | * Class AppController |
||||
39 | * |
||||
40 | * @property AuthUserComponent $AuthUser |
||||
41 | * @property AuthenticationComponent $Authentication |
||||
42 | * @property JsDataComponent $JsData |
||||
43 | * @property RefererComponent $Referer |
||||
44 | * @property SaitoEmailComponent $SaitoEmail |
||||
45 | * @property SlidetabsComponent $Slidetabs |
||||
46 | * @property ThemesComponent $Themes |
||||
47 | * @property TitleComponent $Title |
||||
48 | * @property UsersTable $Users |
||||
49 | */ |
||||
50 | class AppController extends Controller |
||||
51 | { |
||||
52 | use InstanceConfigTrait; |
||||
53 | |||||
54 | public $helpers = [ |
||||
55 | 'Form' => [ |
||||
56 | // Bootstrap 4 CSS-class for invalid input elements |
||||
57 | 'errorClass' => 'is-invalid', |
||||
58 | 'templates' => [ |
||||
59 | // Bootstrap 4 CSS-class for input validation message |
||||
60 | 'error' => '<div class="invalid-feedback">{{content}}</div>', |
||||
61 | ], |
||||
62 | ], |
||||
63 | 'Html', |
||||
64 | 'JsData', |
||||
65 | 'Layout', |
||||
66 | 'Permissions', |
||||
67 | 'SaitoHelp.SaitoHelp', |
||||
68 | 'Stopwatch.Stopwatch', |
||||
69 | 'TimeH', |
||||
70 | 'Url', |
||||
71 | 'User', |
||||
72 | ]; |
||||
73 | |||||
74 | /** |
||||
75 | * Default config used by InstanceConfigTrait |
||||
76 | * |
||||
77 | * @var array default configuration |
||||
78 | */ |
||||
79 | protected $_defaultConfig = [ |
||||
80 | 'showStopwatch' => false, |
||||
81 | ]; |
||||
82 | |||||
83 | /** |
||||
84 | * The current user, set by the AuthUserComponent |
||||
85 | * |
||||
86 | * @var CurrentUserInterface |
||||
87 | */ |
||||
88 | public $CurrentUser; |
||||
89 | |||||
90 | /** |
||||
91 | * {@inheritDoc} |
||||
92 | */ |
||||
93 | public function initialize() |
||||
94 | { |
||||
95 | Stopwatch::start('------------------- Controller -------------------'); |
||||
96 | |||||
97 | parent::initialize(); |
||||
98 | |||||
99 | $this->setConfig('showStopwatch', Configure::read('debug')); |
||||
100 | |||||
101 | if (!$this->request->is('requested')) { |
||||
102 | $this->request->getSession()->start(); |
||||
103 | } |
||||
104 | |||||
105 | Registry::get('Permissions')->buildCategories(TableRegistry::getTableLocator()->get('Categories')); |
||||
106 | |||||
107 | // Leave in front to have it available in all Components |
||||
108 | $this->loadComponent('Detectors.Detectors'); |
||||
109 | $this->loadComponent('Cookie'); |
||||
110 | $this->loadComponent('Authentication.Authentication'); |
||||
111 | $this->loadComponent('Security', ['blackHoleCallback' => 'blackhole']); |
||||
112 | $this->loadComponent('Csrf', ['expiry' => time() + 10800]); |
||||
113 | if (PHP_SAPI !== 'cli') { |
||||
114 | // if: The security mock in testing doesn't allow seeting cookie-name. |
||||
115 | $this->Csrf->setConfig('cookieName', Configure::read('Session.cookie') . '-CSRF'); |
||||
116 | } |
||||
117 | $this->loadComponent('RequestHandler', ['enableBeforeRedirect' => false]); |
||||
118 | $this->loadComponent('Cron.Cron'); |
||||
119 | $this->loadComponent('CacheSupport'); |
||||
120 | $this->loadComponent('AuthUser'); |
||||
121 | $this->loadComponent('Parser'); |
||||
122 | $this->loadComponent('SaitoEmail'); |
||||
123 | $this->loadComponent('Slidetabs'); |
||||
124 | $this->loadComponent('Themes', Configure::read('Saito.themes')); |
||||
125 | $this->loadComponent('Flash'); |
||||
126 | $this->loadComponent('Title'); |
||||
127 | } |
||||
128 | |||||
129 | /** |
||||
130 | * {@inheritDoc} |
||||
131 | */ |
||||
132 | public function beforeFilter(Event $event) |
||||
133 | { |
||||
134 | Stopwatch::start('App->beforeFilter()'); |
||||
135 | |||||
136 | // disable forum with admin pref |
||||
137 | if ( |
||||
138 | Configure::read('Saito.Settings.forum_disabled') && |
||||
139 | $this->request->getParam('action') !== 'login' && |
||||
140 | !$this->CurrentUser->permission('saito.core.admin.backend') |
||||
141 | ) { |
||||
142 | $this->Themes->setDefault(); |
||||
143 | $this->viewBuilder()->enableAutoLayout(false); |
||||
144 | $this->render('/Pages/forum_disabled'); |
||||
145 | $this->response = $this->response->withStatus(503); |
||||
146 | |||||
147 | return null; |
||||
148 | } |
||||
149 | |||||
150 | // allow sql explain for DebugKit toolbar |
||||
151 | if ($this->request->getParam('plugin') === 'debug_kit') { |
||||
152 | $this->Authentication->allowUnauthenticated(['sql_explain']); |
||||
153 | } |
||||
154 | |||||
155 | Stopwatch::stop('App->beforeFilter()'); |
||||
156 | } |
||||
157 | |||||
158 | /** |
||||
159 | * {@inheritDoc} |
||||
160 | */ |
||||
161 | public function beforeRender(Event $event) |
||||
162 | { |
||||
163 | Stopwatch::start('App->beforeRender()'); |
||||
164 | $this->Themes->set($this->CurrentUser); |
||||
165 | $this->_setConfigurationFromGetParams(); |
||||
166 | $this->_l10nRenderFile(); |
||||
167 | |||||
168 | $this->set('SaitoSettings', new SettingsImmutable(Configure::read('Saito.Settings'))); |
||||
169 | $this->set('SaitoEventManager', SaitoEventManager::getInstance()); |
||||
170 | $this->set('showStopwatch', $this->getConfig('showStopwatch')); |
||||
171 | |||||
172 | Stopwatch::stop('App->beforeRender()'); |
||||
173 | Stopwatch::start('------------------- Rendering --------------------'); |
||||
174 | } |
||||
175 | |||||
176 | /** |
||||
177 | * Sets forum configuration from GET parameter in url |
||||
178 | * |
||||
179 | * - theme=<foo> |
||||
180 | * - stopwatch:true |
||||
181 | * - lang:<lang_id> |
||||
182 | * |
||||
183 | * @return void |
||||
184 | */ |
||||
185 | protected function _setConfigurationFromGetParams() |
||||
186 | { |
||||
187 | if (!$this->CurrentUser->isLoggedIn()) { |
||||
188 | return; |
||||
189 | } |
||||
190 | |||||
191 | //= change theme on the fly with ?theme=<name> |
||||
192 | $theme = $this->request->getQuery('theme'); |
||||
193 | if ($theme) { |
||||
194 | $this->Themes->set($this->CurrentUser, $theme); |
||||
0 ignored issues
–
show
It seems like
$theme can also be of type array ; however, parameter $theme of App\Controller\Component\ThemesComponent::set() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
195 | } |
||||
196 | |||||
197 | //= activate stopwatch |
||||
198 | $stopwatch = $this->request->getQuery('stopwatch'); |
||||
199 | if ( |
||||
200 | $stopwatch && Configure::read('Saito.Settings.stopwatch_get') |
||||
201 | ) { |
||||
202 | $this->setConfig('showStopwatch', true); |
||||
203 | }; |
||||
204 | |||||
205 | //= change language |
||||
206 | $lang = $this->request->getQuery('lang'); |
||||
207 | if (!empty($lang)) { |
||||
208 | Configure::write('Saito.language', $lang); |
||||
209 | }; |
||||
210 | } |
||||
211 | |||||
212 | /** |
||||
213 | * Handle request-blackhole. |
||||
214 | * |
||||
215 | * @param string $type type |
||||
216 | * @return void |
||||
217 | * @throws \Saito\Exception\SaitoBlackholeException |
||||
218 | */ |
||||
219 | public function blackhole($type) |
||||
220 | { |
||||
221 | throw new \Saito\Exception\SaitoBlackholeException( |
||||
222 | $type, |
||||
223 | ['CurrentUser' => $this->CurrentUser] |
||||
224 | ); |
||||
225 | } |
||||
226 | |||||
227 | /** |
||||
228 | * manually require auth and redirect cycle |
||||
229 | * |
||||
230 | * @return Response |
||||
231 | */ |
||||
232 | protected function _requireAuth() |
||||
233 | { |
||||
234 | $this->Flash->set(__('authorization.autherror'), ['element' => 'error']); |
||||
235 | $here = $this->request->getRequestTarget(); |
||||
236 | |||||
237 | return $this->redirect([ |
||||
238 | '_name' => 'login', |
||||
239 | '?' => ['redirect' => $here], |
||||
240 | 'plugin' => false, |
||||
241 | ]); |
||||
242 | } |
||||
243 | |||||
244 | /** |
||||
245 | * sets l10n .ctp file if available |
||||
246 | * |
||||
247 | * @return void |
||||
248 | */ |
||||
249 | protected function _l10nRenderFile() |
||||
250 | { |
||||
251 | $locale = Configure::read('Saito.language'); |
||||
252 | I18n::useFallback(false); // @see <https://github.com/cakephp/cakephp/pull/6812> |
||||
253 | I18n::setLocale($locale); |
||||
254 | if (!$locale) { |
||||
255 | return; |
||||
256 | } |
||||
257 | |||||
258 | $check = function ($locale) { |
||||
259 | $l10nViewPath = $this->viewBuilder()->getTemplatePath() . DS . $locale; |
||||
260 | $l10nViewFile = $l10nViewPath . DS . $this->viewBuilder()->getName() . '.ctp'; |
||||
261 | if (!file_exists(APP . 'Template' . DS . $l10nViewFile)) { |
||||
262 | return false; |
||||
263 | } |
||||
264 | |||||
265 | return $l10nViewPath; |
||||
266 | }; |
||||
267 | |||||
268 | $path = $check($locale); |
||||
269 | if ($path) { |
||||
270 | $this->viewBuilder()->templatePath($path); |
||||
0 ignored issues
–
show
The function
Cake\View\ViewBuilder::templatePath() has been deprecated: 3.4.0 Use setTemplatePath()/getTemplatePath() instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
271 | |||||
272 | return; |
||||
273 | } |
||||
274 | |||||
275 | if (strpos($locale, '_')) { |
||||
276 | list($locale) = explode('_', $locale); |
||||
277 | $path = $check($locale); |
||||
278 | if ($path) { |
||||
279 | $this->viewBuilder()->templatePath($path); |
||||
0 ignored issues
–
show
The function
Cake\View\ViewBuilder::templatePath() has been deprecated: 3.4.0 Use setTemplatePath()/getTemplatePath() instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
280 | } |
||||
281 | } |
||||
282 | } |
||||
283 | } |
||||
284 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths