1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the TYPO3 CMS project. |
5
|
|
|
* |
6
|
|
|
* It is free software; you can redistribute it and/or modify it under |
7
|
|
|
* the terms of the GNU General Public License, either version 2 |
8
|
|
|
* of the License, or any later version. |
9
|
|
|
* |
10
|
|
|
* For the full copyright and license information, please read the |
11
|
|
|
* LICENSE.txt file that was distributed with this source code. |
12
|
|
|
* |
13
|
|
|
* The TYPO3 project - inspiring people to share! |
14
|
|
|
*/ |
15
|
|
|
|
16
|
|
|
namespace TYPO3\CMS\Beuser\Controller; |
17
|
|
|
|
18
|
|
|
use TYPO3\CMS\Backend\Template\Components\ButtonBar; |
19
|
|
|
use TYPO3\CMS\Backend\Tree\View\PageTreeView; |
20
|
|
|
use TYPO3\CMS\Backend\Utility\BackendUtility; |
21
|
|
|
use TYPO3\CMS\Backend\View\BackendTemplateView; |
22
|
|
|
use TYPO3\CMS\Core\DataHandling\DataHandler; |
23
|
|
|
use TYPO3\CMS\Core\Imaging\Icon; |
24
|
|
|
use TYPO3\CMS\Core\Messaging\FlashMessage; |
25
|
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility; |
26
|
|
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; |
27
|
|
|
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; |
28
|
|
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Backend module page permissions |
32
|
|
|
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API. |
33
|
|
|
*/ |
34
|
|
|
class PermissionController extends ActionController |
35
|
|
|
{ |
36
|
|
|
/** |
37
|
|
|
* @var string prefix for session |
38
|
|
|
*/ |
39
|
|
|
const SESSION_PREFIX = 'tx_Beuser_'; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var int the current page id |
43
|
|
|
*/ |
44
|
|
|
protected $id; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @var string |
48
|
|
|
*/ |
49
|
|
|
protected $returnUrl = ''; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @var int |
53
|
|
|
*/ |
54
|
|
|
protected $depth; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Number of levels to enable recursive settings for |
58
|
|
|
* |
59
|
|
|
* @var int |
60
|
|
|
*/ |
61
|
|
|
protected $getLevels = 10; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @var array |
65
|
|
|
*/ |
66
|
|
|
protected $pageInfo = []; |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Backend Template Container |
70
|
|
|
* |
71
|
|
|
* @var string |
72
|
|
|
*/ |
73
|
|
|
protected $defaultViewObjectName = BackendTemplateView::class; |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* BackendTemplateContainer |
77
|
|
|
* |
78
|
|
|
* @var BackendTemplateView |
79
|
|
|
*/ |
80
|
|
|
protected $view; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Initialize action |
84
|
|
|
*/ |
85
|
|
|
protected function initializeAction() |
86
|
|
|
{ |
87
|
|
|
// determine depth parameter |
88
|
|
|
$this->depth = (int)GeneralUtility::_GP('depth') > 0 |
89
|
|
|
? (int)GeneralUtility::_GP('depth') |
90
|
|
|
: (int)$this->getBackendUser()->getSessionData(self::SESSION_PREFIX . 'depth'); |
91
|
|
|
if ($this->request->hasArgument('depth')) { |
92
|
|
|
$this->depth = (int)$this->request->getArgument('depth'); |
93
|
|
|
} |
94
|
|
|
$this->getBackendUser()->setAndSaveSessionData(self::SESSION_PREFIX . 'depth', $this->depth); |
95
|
|
|
|
96
|
|
|
// determine id parameter |
97
|
|
|
$this->id = (int)GeneralUtility::_GP('id'); |
98
|
|
|
if ($this->request->hasArgument('id')) { |
99
|
|
|
$this->id = (int)$this->request->getArgument('id'); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
if (!BackendUtility::getRecord('pages', $this->id)) { |
103
|
|
|
$this->id = 0; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
$this->returnUrl = GeneralUtility::_GP('returnUrl'); |
107
|
|
|
if ($this->request->hasArgument('returnUrl')) { |
108
|
|
|
$this->returnUrl = $this->request->getArgument('returnUrl'); |
|
|
|
|
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
$this->setPageInfo(); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Initializes view |
116
|
|
|
* |
117
|
|
|
* @param ViewInterface $view The view to be initialized |
118
|
|
|
*/ |
119
|
|
|
protected function initializeView(ViewInterface $view) |
120
|
|
|
{ |
121
|
|
|
parent::initializeView($view); |
122
|
|
|
$this->setPageInfo(); |
123
|
|
|
|
124
|
|
|
// the view of the update action has a different view class |
125
|
|
|
if ($view instanceof BackendTemplateView) { |
126
|
|
|
$view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Beuser/Permissions'); |
127
|
|
|
$view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip'); |
128
|
|
|
|
129
|
|
|
$this->registerDocHeaderButtons(); |
130
|
|
|
$this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($this->pageInfo); |
|
|
|
|
131
|
|
|
$this->view->getModuleTemplate()->setFlashMessageQueue($this->getFlashMessageQueue()); |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Registers the Icons into the docheader |
137
|
|
|
* |
138
|
|
|
* @throws \InvalidArgumentException |
139
|
|
|
*/ |
140
|
|
|
protected function registerDocHeaderButtons() |
141
|
|
|
{ |
142
|
|
|
/** @var ButtonBar $buttonBar */ |
143
|
|
|
$buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar(); |
144
|
|
|
$currentRequest = $this->request; |
145
|
|
|
$moduleName = $currentRequest->getPluginName(); |
146
|
|
|
$lang = $this->getLanguageService(); |
147
|
|
|
|
148
|
|
|
if ($currentRequest->getControllerActionName() === 'edit') { |
149
|
|
|
// CLOSE button: |
150
|
|
|
if (!empty($this->returnUrl)) { |
151
|
|
|
$closeButton = $buttonBar->makeLinkButton() |
152
|
|
|
->setHref($this->returnUrl) |
153
|
|
|
->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc')) |
154
|
|
|
->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon( |
155
|
|
|
'actions-close', |
156
|
|
|
Icon::SIZE_SMALL |
157
|
|
|
)); |
158
|
|
|
$buttonBar->addButton($closeButton); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
// SAVE button: |
162
|
|
|
$saveButton = $buttonBar->makeInputButton() |
163
|
|
|
->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveCloseDoc')) |
164
|
|
|
->setName('tx_beuser_system_beusertxpermission[submit]') |
165
|
|
|
->setValue('Save') |
166
|
|
|
->setForm('PermissionControllerEdit') |
167
|
|
|
->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon( |
168
|
|
|
'actions-document-save', |
169
|
|
|
Icon::SIZE_SMALL |
170
|
|
|
)) |
171
|
|
|
->setShowLabelText(true); |
172
|
|
|
|
173
|
|
|
$buttonBar->addButton($saveButton); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
$shortcutButton = $buttonBar->makeShortcutButton() |
177
|
|
|
->setModuleName($moduleName) |
178
|
|
|
->setDisplayName($this->getShortcutTitle()) |
179
|
|
|
->setArguments([ |
180
|
|
|
'route' => GeneralUtility::_GP('route'), |
181
|
|
|
'id' => (int)$this->id, |
182
|
|
|
]); |
183
|
|
|
$buttonBar->addButton($shortcutButton); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Index action |
188
|
|
|
*/ |
189
|
|
|
public function indexAction() |
190
|
|
|
{ |
191
|
|
|
if (!$this->id) { |
192
|
|
|
$this->pageInfo = ['title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'uid' => 0, 'pid' => 0]; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
if ($this->getBackendUser()->workspace != 0) { |
196
|
|
|
// Adding section with the permission setting matrix: |
197
|
|
|
$this->addFlashMessage( |
198
|
|
|
LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser') ?? '', |
199
|
|
|
LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser') ?? '', |
200
|
|
|
FlashMessage::WARNING |
201
|
|
|
); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
// depth options |
205
|
|
|
$depthOptions = []; |
206
|
|
|
$url = $this->uriBuilder->reset()->setArguments([ |
207
|
|
|
'action' => 'index', |
208
|
|
|
'depth' => '${value}', |
209
|
|
|
'id' => $this->id |
210
|
|
|
])->buildBackendUri(); |
211
|
|
|
foreach ([1, 2, 3, 4, 10] as $depthLevel) { |
212
|
|
|
$levelLabel = $depthLevel === 1 ? 'level' : 'levels'; |
213
|
|
|
$depthOptions[$depthLevel] = $depthLevel . ' ' . LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:' . $levelLabel, 'beuser'); |
214
|
|
|
} |
215
|
|
|
$this->view->assign('currentId', $this->id); |
216
|
|
|
$this->view->assign('depthBaseUrl', $url); |
217
|
|
|
$this->view->assign('depth', $this->depth); |
218
|
|
|
$this->view->assign('depthOptions', $depthOptions); |
219
|
|
|
|
220
|
|
|
$beUserArray = BackendUtility::getUserNames(); |
221
|
|
|
$this->view->assign('beUsers', $beUserArray); |
222
|
|
|
$beGroupArray = BackendUtility::getGroupNames(); |
223
|
|
|
$this->view->assign('beGroups', $beGroupArray); |
224
|
|
|
|
225
|
|
|
/** @var PageTreeView $tree */ |
226
|
|
|
$tree = GeneralUtility::makeInstance(PageTreeView::class); |
227
|
|
|
$tree->init(); |
228
|
|
|
$tree->addField('perms_user', true); |
229
|
|
|
$tree->addField('perms_group', true); |
230
|
|
|
$tree->addField('perms_everybody', true); |
231
|
|
|
$tree->addField('perms_userid', true); |
232
|
|
|
$tree->addField('perms_groupid', true); |
233
|
|
|
$tree->addField('hidden'); |
234
|
|
|
$tree->addField('fe_group'); |
235
|
|
|
$tree->addField('starttime'); |
236
|
|
|
$tree->addField('endtime'); |
237
|
|
|
$tree->addField('editlock'); |
238
|
|
|
|
239
|
|
|
// Create the tree from $this->id |
240
|
|
|
if ($this->id) { |
241
|
|
|
$tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getIcon($this->pageInfo)]; |
242
|
|
|
} else { |
243
|
|
|
$tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getRootIcon($this->pageInfo)]; |
244
|
|
|
} |
245
|
|
|
$tree->getTree($this->id, $this->depth); |
246
|
|
|
$this->view->assign('viewTree', $tree->tree); |
247
|
|
|
|
248
|
|
|
// CSH for permissions setting |
249
|
|
|
$this->view->assign('cshItem', BackendUtility::cshItem('xMOD_csh_corebe', 'perm_module', '', '<span class="btn btn-default btn-sm">|</span>')); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Edit action |
254
|
|
|
*/ |
255
|
|
|
public function editAction() |
256
|
|
|
{ |
257
|
|
|
$this->view->assign('id', $this->id); |
258
|
|
|
$this->view->assign('depth', $this->depth); |
259
|
|
|
|
260
|
|
|
if (!$this->id) { |
261
|
|
|
$this->pageInfo = ['title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'uid' => 0, 'pid' => 0]; |
262
|
|
|
} |
263
|
|
|
if ($this->getBackendUser()->workspace != 0) { |
264
|
|
|
// Adding FlashMessage with the permission setting matrix: |
265
|
|
|
$this->addFlashMessage( |
266
|
|
|
LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser') ?? '', |
267
|
|
|
LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser') ?? '', |
268
|
|
|
FlashMessage::WARNING |
269
|
|
|
); |
270
|
|
|
} |
271
|
|
|
// Get user names and group names |
272
|
|
|
$beGroupArray = BackendUtility::getGroupNames(); |
273
|
|
|
$beUserArray = BackendUtility::getUserNames(); |
274
|
|
|
|
275
|
|
|
// Owner selector |
276
|
|
|
$beUserDataArray = [0 => LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone', 'beuser')]; |
277
|
|
|
foreach ($beUserArray as $uid => &$row) { |
278
|
|
|
$beUserDataArray[$uid] = $row['username']; |
279
|
|
|
} |
280
|
|
|
$beUserDataArray[-1] = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged', 'beuser'); |
281
|
|
|
$this->view->assign('currentBeUser', $this->pageInfo['perms_userid']); |
282
|
|
|
$this->view->assign('beUserData', $beUserDataArray); |
283
|
|
|
|
284
|
|
|
// Group selector |
285
|
|
|
$beGroupDataArray = [0 => LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone', 'beuser')]; |
286
|
|
|
foreach ($beGroupArray as $uid => $row) { |
287
|
|
|
$beGroupDataArray[$uid] = $row['title']; |
288
|
|
|
} |
289
|
|
|
$beGroupDataArray[-1] = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged', 'beuser'); |
290
|
|
|
$this->view->assign('currentBeGroup', $this->pageInfo['perms_groupid']); |
291
|
|
|
$this->view->assign('beGroupData', $beGroupDataArray); |
292
|
|
|
$this->view->assign('pageInfo', $this->pageInfo); |
293
|
|
|
$this->view->assign('returnUrl', $this->returnUrl); |
294
|
|
|
$this->view->assign('recursiveSelectOptions', $this->getRecursiveSelectOptions()); |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Update action |
299
|
|
|
* |
300
|
|
|
* @param array $data |
301
|
|
|
* @param array $mirror |
302
|
|
|
*/ |
303
|
|
|
protected function updateAction(array $data, array $mirror) |
304
|
|
|
{ |
305
|
|
|
$dataHandlerInput = []; |
306
|
|
|
// Prepare the input data for data handler |
307
|
|
|
if (!empty($data['pages'])) { |
308
|
|
|
foreach ($data['pages'] as $pageUid => $properties) { |
309
|
|
|
// if the owner and group field shouldn't be touched, unset the option |
310
|
|
|
if ((int)$properties['perms_userid'] === -1) { |
311
|
|
|
unset($properties['perms_userid']); |
312
|
|
|
} |
313
|
|
|
if ((int)$properties['perms_groupid'] === -1) { |
314
|
|
|
unset($properties['perms_groupid']); |
315
|
|
|
} |
316
|
|
|
$dataHandlerInput[$pageUid] = $properties; |
317
|
|
|
if (!empty($mirror['pages'][$pageUid])) { |
318
|
|
|
$mirrorPages = GeneralUtility::intExplode(',', $mirror['pages'][$pageUid]); |
319
|
|
|
foreach ($mirrorPages as $mirrorPageUid) { |
320
|
|
|
$dataHandlerInput[$mirrorPageUid] = $properties; |
321
|
|
|
} |
322
|
|
|
} |
323
|
|
|
} |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
$dataHandler = GeneralUtility::makeInstance(DataHandler::class); |
327
|
|
|
$dataHandler->start( |
328
|
|
|
[ |
329
|
|
|
'pages' => $dataHandlerInput |
330
|
|
|
], |
331
|
|
|
[] |
332
|
|
|
); |
333
|
|
|
$dataHandler->process_datamap(); |
334
|
|
|
|
335
|
|
|
$this->redirectToUri($this->returnUrl); |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
/** |
339
|
|
|
* @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication |
340
|
|
|
*/ |
341
|
|
|
protected function getBackendUser() |
342
|
|
|
{ |
343
|
|
|
return $GLOBALS['BE_USER']; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* Finding tree and offer setting of values recursively. |
348
|
|
|
* |
349
|
|
|
* @return array |
350
|
|
|
*/ |
351
|
|
|
protected function getRecursiveSelectOptions() |
352
|
|
|
{ |
353
|
|
|
// Initialize tree object: |
354
|
|
|
$tree = GeneralUtility::makeInstance(PageTreeView::class); |
355
|
|
|
$tree->init(); |
356
|
|
|
$tree->addField('perms_userid', true); |
357
|
|
|
$tree->makeHTML = 0; |
358
|
|
|
$tree->setRecs = 1; |
359
|
|
|
// Make tree: |
360
|
|
|
$tree->getTree($this->id, $this->getLevels, ''); |
361
|
|
|
$options = []; |
362
|
|
|
$options[''] = ''; |
363
|
|
|
// If there are a hierarchy of page ids, then... |
364
|
|
|
if ($this->getBackendUser()->user['uid'] && !empty($tree->orig_ids_hierarchy)) { |
365
|
|
|
// Init: |
366
|
|
|
$labelRecursive = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:recursive', 'beuser'); |
367
|
|
|
$labelLevel = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:level', 'beuser'); |
368
|
|
|
$labelLevels = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:levels', 'beuser'); |
369
|
|
|
$labelPageAffected = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:page_affected', 'beuser'); |
370
|
|
|
$labelPagesAffected = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:pages_affected', 'beuser'); |
371
|
|
|
$theIdListArr = []; |
372
|
|
|
// Traverse the number of levels we want to allow recursive |
373
|
|
|
// setting of permissions for: |
374
|
|
|
for ($a = $this->getLevels; $a > 0; $a--) { |
375
|
|
|
if (is_array($tree->orig_ids_hierarchy[$a])) { |
376
|
|
|
foreach ($tree->orig_ids_hierarchy[$a] as $theId) { |
377
|
|
|
$theIdListArr[] = $theId; |
378
|
|
|
} |
379
|
|
|
$lKey = $this->getLevels - $a + 1; |
380
|
|
|
$pagesCount = count($theIdListArr); |
381
|
|
|
$options[implode(',', $theIdListArr)] = $labelRecursive . ' ' . $lKey . ' ' . ($lKey === 1 ? $labelLevel : $labelLevels) . |
382
|
|
|
' (' . $pagesCount . ' ' . ($pagesCount === 1 ? $labelPageAffected : $labelPagesAffected) . ')'; |
383
|
|
|
} |
384
|
|
|
} |
385
|
|
|
} |
386
|
|
|
return $options; |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
/** |
390
|
|
|
* Check if page record exists and set pageInfo |
391
|
|
|
*/ |
392
|
|
|
protected function setPageInfo(): void |
393
|
|
|
{ |
394
|
|
|
$this->pageInfo = BackendUtility::readPageAccess(BackendUtility::getRecord('pages', $this->id) ? $this->id : 0, ' 1=1'); |
|
|
|
|
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
/** |
398
|
|
|
* Returns LanguageService |
399
|
|
|
* |
400
|
|
|
* @return \TYPO3\CMS\Core\Localization\LanguageService |
401
|
|
|
*/ |
402
|
|
|
protected function getLanguageService() |
403
|
|
|
{ |
404
|
|
|
return $GLOBALS['LANG']; |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Returns the shortcut title for the current page |
409
|
|
|
* |
410
|
|
|
* @return string |
411
|
|
|
*/ |
412
|
|
|
protected function getShortcutTitle(): string |
413
|
|
|
{ |
414
|
|
|
return sprintf( |
415
|
|
|
'%s: %s [%d]', |
416
|
|
|
$this->getLanguageService()->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'), |
417
|
|
|
BackendUtility::getRecordTitle('pages', $this->pageInfo), |
418
|
|
|
$this->id |
419
|
|
|
); |
420
|
|
|
} |
421
|
|
|
} |
422
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.