PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/backend/modules/users/actions/edit.php

https://github.com/lowiebenoot/forkcms
PHP | 354 lines | 194 code | 55 blank | 105 comment | 61 complexity | c67456712d5ccfc94a12c0196b4693e8 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of Fork CMS.
  4. *
  5. * For the full copyright and license information, please view the license
  6. * file that was distributed with this source code.
  7. */
  8. use Symfony\Component\Filesystem\Filesystem;
  9. use Symfony\Component\Filesystem\Exception\IOException;
  10. /**
  11. * This is the edit-action, it will display a form to alter the user-details and settings
  12. *
  13. * @author Tijs Verkoyen <tijs@sumocoders.be>
  14. * @author Jelmer Snoeck <jelmer@siphoc.com>
  15. * @author Annelies Van Extergem <annelies.vanextergem@netlash.com>
  16. * @author Siesqo <info@siesqo.be>
  17. */
  18. class BackendUsersEdit extends BackendBaseActionEdit
  19. {
  20. /**
  21. * The authenticated user
  22. *
  23. * @var BackendUser
  24. */
  25. private $authenticatedUser;
  26. /**
  27. * Can only edit his own profile
  28. *
  29. * @var bool
  30. */
  31. private $allowUserRights;
  32. /**
  33. * The user
  34. *
  35. * @var BackendUser
  36. */
  37. private $user;
  38. /**
  39. * Execute the action
  40. */
  41. public function execute()
  42. {
  43. $this->id = $this->getParameter('id', 'int');
  44. // does the user exists
  45. if($this->id !== null && BackendUsersModel::exists($this->id))
  46. {
  47. parent::execute();
  48. $this->record = (array) BackendUsersModel::get($this->id);
  49. $this->loadForm();
  50. $this->validateForm();
  51. $this->parse();
  52. $this->display();
  53. }
  54. // no user found, throw an exceptions, because somebody is fucking with our URL
  55. else $this->redirect(BackendModel::createURLForAction('index') . '&error=non-existing');
  56. }
  57. /**
  58. * Load the form
  59. */
  60. private function loadForm()
  61. {
  62. // create user objects
  63. $this->user = new BackendUser($this->id);
  64. $this->authenticatedUser = BackendAuthentication::getUser();
  65. $this->allowUserRights = ((BackendAuthentication::isAllowedAction('index') || $this->authenticatedUser->getUserId() != $this->id) || $this->authenticatedUser->isGod());
  66. // redirect to error page when not allowed to edit other profiles
  67. if(!$this->authenticatedUser->isGod() && ($this->authenticatedUser->getUserId() != $this->id && !BackendAuthentication::isAllowedAction('index')))
  68. {
  69. $this->redirect(BackendModel::createURLForAction('error') . '&type=not-allowed');
  70. }
  71. // create form
  72. $this->frm = new BackendForm('edit');
  73. // get active groups
  74. $groups = BackendGroupsModel::getGroupsByUser($this->id);
  75. // loop through groups and set checked
  76. foreach($groups as $group) $checkedGroups[] = $group['id'];
  77. // create elements
  78. // profile
  79. $this->frm->addText('email', $this->record['email'], 255);
  80. if($this->user->isGod()) $this->frm->getField('email')->setAttributes(array('disabled' => 'disabled'));
  81. $this->frm->addText('name', $this->record['settings']['name'], 255);
  82. $this->frm->addText('surname', $this->record['settings']['surname'], 255);
  83. $this->frm->addText('nickname', $this->record['settings']['nickname'], 24);
  84. $this->frm->addImage('avatar');
  85. // password
  86. // check if we're god or same user
  87. if($this->authenticatedUser->getUserId() == $this->id || $this->authenticatedUser->isGod())
  88. {
  89. // allow to set new password
  90. $this->frm->addPassword('new_password', null, 75);
  91. $this->frm->addPassword('confirm_password', null, 75);
  92. // disable autocomplete
  93. $this->frm->getField('new_password')->setAttributes(array('autocomplete' => 'off'));
  94. $this->frm->getField('confirm_password')->setAttributes(array('autocomplete' => 'off'));
  95. }
  96. // settings
  97. $this->frm->addDropdown('interface_language', BackendLanguage::getInterfaceLanguages(), $this->record['settings']['interface_language']);
  98. $this->frm->addDropdown('date_format', BackendUsersModel::getDateFormats(), $this->user->getSetting('date_format'));
  99. $this->frm->addDropdown('time_format', BackendUsersModel::getTimeFormats(), $this->user->getSetting('time_format'));
  100. $this->frm->addDropdown('number_format', BackendUsersModel::getNumberFormats(), $this->user->getSetting('number_format', 'dot_nothing'));
  101. $this->frm->addDropDown('csv_split_character', BackendUsersModel::getCSVSplitCharacters(), $this->user->getSetting('csv_split_character'));
  102. $this->frm->addDropDown('csv_line_ending', BackendUsersModel::getCSVLineEndings(), $this->user->getSetting('csv_line_ending'));
  103. // permissions
  104. $this->frm->addCheckbox('active', ($this->record['active'] == 'Y'));
  105. // only when GOD or when you can edit other users
  106. if($this->allowUserRights)
  107. {
  108. // disable active field for current users
  109. if($this->authenticatedUser->getUserId() == $this->record['id']) $this->frm->getField('active')->setAttribute('disabled', 'disabled');
  110. $this->frm->addCheckbox('api_access', (isset($this->record['settings']['api_access']) && $this->record['settings']['api_access'] == 'Y'));
  111. $this->frm->addMultiCheckbox('groups', BackendGroupsModel::getAll(), $checkedGroups);
  112. }
  113. }
  114. /**
  115. * Parse the form
  116. */
  117. protected function parse()
  118. {
  119. parent::parse();
  120. // reset avatar URL
  121. if($this->record['settings']['avatar'] != '') $this->record['settings']['avatar'] .= '?time=' . time();
  122. // only allow deletion of other users
  123. $this->tpl->assign('showUsersDelete', $this->authenticatedUser->getUserId() != $this->id && BackendAuthentication::isAllowedAction('delete'));
  124. // assign
  125. $this->tpl->assign('record', $this->record);
  126. $this->tpl->assign('id', $this->id);
  127. // assign that we're god or the same user
  128. $this->tpl->assign('allowPasswordEdit', ($this->authenticatedUser->getUserId() == $this->id || $this->authenticatedUser->isGod()));
  129. // assign that you can edit the user rights
  130. $this->tpl->assign('allowUserRights', $this->allowUserRights);
  131. // check if we need to show the password strength and parse the label
  132. $this->tpl->assign('showPasswordStrength', ($this->record['settings']['password_strength'] !== 'strong'));
  133. $this->tpl->assign('passwordStrengthLabel', BL::lbl($this->record['settings']['password_strength']));
  134. }
  135. /**
  136. * Validate the form
  137. */
  138. private function validateForm()
  139. {
  140. // is the form submitted?
  141. if($this->frm->isSubmitted())
  142. {
  143. // cleanup the submitted fields, ignore fields that were added by hackers
  144. $this->frm->cleanupFields();
  145. $fields = $this->frm->getFields();
  146. // email is present
  147. if(!$this->user->isGod())
  148. {
  149. if($fields['email']->isFilled(BL::err('EmailIsRequired')))
  150. {
  151. // is this an email-address
  152. if($fields['email']->isEmail(BL::err('EmailIsInvalid')))
  153. {
  154. // was this emailaddress deleted before
  155. if(BackendUsersModel::emailDeletedBefore($fields['email']->getValue()))
  156. {
  157. $fields['email']->addError(sprintf(BL::err('EmailWasDeletedBefore'), BackendModel::createURLForAction('undo_delete', null, null, array('email' => $fields['email']->getValue()))));
  158. }
  159. // email already exists
  160. elseif(BackendUsersModel::existsEmail($fields['email']->getValue(), $this->id))
  161. {
  162. $fields['email']->addError(BL::err('EmailAlreadyExists'));
  163. }
  164. }
  165. }
  166. }
  167. // required fields
  168. if($this->user->isGod() && $fields['email']->getValue() != '' && $this->user->getEmail() != $fields['email']->getValue()) $fields['email']->addError(BL::err('CantChangeGodsEmail'));
  169. if(!$this->user->isGod()) $fields['email']->isEmail(BL::err('EmailIsInvalid'));
  170. $fields['nickname']->isFilled(BL::err('NicknameIsRequired'));
  171. $fields['name']->isFilled(BL::err('NameIsRequired'));
  172. $fields['surname']->isFilled(BL::err('SurnameIsRequired'));
  173. $fields['interface_language']->isFilled(BL::err('FieldIsRequired'));
  174. $fields['date_format']->isFilled(BL::err('FieldIsRequired'));
  175. $fields['time_format']->isFilled(BL::err('FieldIsRequired'));
  176. $fields['number_format']->isFilled(BL::err('FieldIsRequired'));
  177. if($this->allowUserRights) $fields['groups']->isFilled(BL::err('FieldIsRequired'));
  178. if(isset($fields['new_password']) && $fields['new_password']->isFilled())
  179. {
  180. if($fields['new_password']->getValue() !== $fields['confirm_password']->getValue()) $fields['confirm_password']->addError(BL::err('ValuesDontMatch'));
  181. }
  182. // validate avatar
  183. if($fields['avatar']->isFilled())
  184. {
  185. // correct extension
  186. if($fields['avatar']->isAllowedExtension(array('jpg', 'jpeg', 'gif', 'png'), BL::err('JPGGIFAndPNGOnly')))
  187. {
  188. // correct mimetype?
  189. $fields['avatar']->isAllowedMimeType(array('image/gif', 'image/jpg', 'image/jpeg', 'image/png'), BL::err('JPGGIFAndPNGOnly'));
  190. }
  191. }
  192. // no errors?
  193. if($this->frm->isCorrect())
  194. {
  195. // build user-array
  196. $user['id'] = $this->id;
  197. if(!$this->user->isGod()) $user['email'] = $fields['email']->getValue(true);
  198. if($this->authenticatedUser->getUserId() != $this->record['id']) $user['active'] = ($fields['active']->isChecked()) ? 'Y' : 'N';
  199. // build settings-array
  200. $settings['nickname'] = $fields['nickname']->getValue();
  201. $settings['name'] = $fields['name']->getValue();
  202. $settings['surname'] = $fields['surname']->getValue();
  203. $settings['interface_language'] = $fields['interface_language']->getValue();
  204. $settings['date_format'] = $fields['date_format']->getValue();
  205. $settings['time_format'] = $fields['time_format']->getValue();
  206. $settings['datetime_format'] = $settings['date_format'] . ' ' . $settings['time_format'];
  207. $settings['number_format'] = $fields['number_format']->getValue();
  208. $settings['csv_split_character'] = $fields['csv_split_character']->getValue();
  209. $settings['csv_line_ending'] = $fields['csv_line_ending']->getValue();
  210. $settings['api_access'] = ($this->allowUserRights) ? (bool) $fields['api_access']->getChecked() : $this->record['settings']['api_access'];
  211. // update password (only if filled in)
  212. if(isset($fields['new_password']) && $fields['new_password']->isFilled())
  213. {
  214. $user['password'] = BackendAuthentication::getEncryptedString($fields['new_password']->getValue(), $this->record['settings']['password_key']);
  215. // the password has changed
  216. if($this->record['password'] != $user['password'])
  217. {
  218. // save the login timestamp in the user's settings
  219. $lastPasswordChange = BackendUsersModel::getSetting($user['id'], 'current_password_change');
  220. $settings['current_password_change'] = time();
  221. if($lastPasswordChange) $settings['last_password_change'] = $lastPasswordChange;
  222. // save the password strength
  223. $passwordStrength = BackendAuthentication::checkPassword($fields['new_password']->getValue());
  224. $settings['password_strength'] = $passwordStrength;
  225. }
  226. }
  227. // get user groups when allowed to edit
  228. if($this->allowUserRights)
  229. {
  230. // get selected groups
  231. $groups = $fields['groups']->getChecked();
  232. // init var
  233. $newSequence = BackendGroupsModel::getSetting($groups[0], 'dashboard_sequence');
  234. // loop through groups and collect all dashboard widget sequences
  235. foreach($groups as $group) $sequences[] = BackendGroupsModel::getSetting($group, 'dashboard_sequence');
  236. // loop through sequences
  237. foreach($sequences as $sequence)
  238. {
  239. // loop through modules inside a sequence
  240. foreach($sequence as $moduleKey => $module)
  241. {
  242. // loop through widgets inside a module
  243. foreach($module as $widgetKey => $widget)
  244. {
  245. // if widget present set true
  246. if($widget['present']) $newSequence[$moduleKey][$widgetKey]['present'] = true;
  247. }
  248. }
  249. }
  250. // add new sequence to settings
  251. $settings['dashboard_sequence'] = $newSequence;
  252. }
  253. // has the user submitted an avatar?
  254. if($fields['avatar']->isFilled())
  255. {
  256. // init vars
  257. $avatarsPath = FRONTEND_FILES_PATH . '/backend_users/avatars';
  258. // delete old avatar if it isn't the default-image
  259. if($this->record['settings']['avatar'] != 'no-avatar.jpg' && $this->record['settings']['avatar'] != '')
  260. {
  261. $fs = new Filesystem();
  262. $fs->remove($avatarsPath . '/source/' . $this->record['settings']['avatar']);
  263. $fs->remove($avatarsPath . '/128x128/' . $this->record['settings']['avatar']);
  264. $fs->remove($avatarsPath . '/64x64/' . $this->record['settings']['avatar']);
  265. $fs->remove($avatarsPath . '/32x32/' . $this->record['settings']['avatar']);
  266. }
  267. // create new filename
  268. $filename = rand(0,3) . '_' . $user['id'] . '.' . $fields['avatar']->getExtension();
  269. // add into settings to update
  270. $settings['avatar'] = $filename;
  271. // resize (128x128)
  272. $fields['avatar']->createThumbnail($avatarsPath . '/128x128/' . $filename, 128, 128, true, false, 100);
  273. // resize (64x64)
  274. $fields['avatar']->createThumbnail($avatarsPath . '/64x64/' . $filename, 64, 64, true, false, 100);
  275. // resize (32x32)
  276. $fields['avatar']->createThumbnail($avatarsPath . '/32x32/' . $filename, 32, 32, true, false, 100);
  277. }
  278. // save changes
  279. BackendUsersModel::update($user, $settings);
  280. // save groups
  281. if($this->allowUserRights) BackendGroupsModel::insertMultipleGroups($this->id, $groups);
  282. // trigger event
  283. BackendModel::triggerEvent($this->getModule(), 'after_edit', array('item' => $user));
  284. // can only edit own profile
  285. if(!BackendAuthentication::isAllowedAction('index'))
  286. {
  287. // everything is saved, so redirect to the edit page
  288. $this->redirect(BackendModel::createURLForAction('edit') . '&id=' . $this->id . '&report=edited&var=' . $settings['nickname']);
  289. }
  290. // can view other users
  291. else
  292. {
  293. // everything is saved, so redirect to the overview
  294. $this->redirect(BackendModel::createURLForAction('index') . '&report=edited&var=' . $settings['nickname'] . '&highlight=row-' . $user['id']);
  295. }
  296. }
  297. }
  298. }
  299. }