PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/ojs/ojs-2.3.1-2/plugins/importexport/users/UserXMLParser.inc.php

https://github.com/mcrider/pkpUpgradeTestSuite
PHP | 416 lines | 263 code | 50 blank | 103 comment | 50 complexity | 3f7413b6f7abdf68e824245e286caa3d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @file UserXMLParser.inc.php
  4. *
  5. * Copyright (c) 2003-2009 John Willinsky
  6. * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  7. *
  8. * @class UserXMLParser
  9. * @ingroup plugins_importexport_users
  10. *
  11. * @brief Class to import and export user data from an XML format.
  12. * See dbscripts/xml/dtd/users.dtd for the XML schema used.
  13. */
  14. // $Id: UserXMLParser.inc.php,v 1.22 2009/05/13 00:14:46 asmecher Exp $
  15. import('xml.XMLParser');
  16. class UserXMLParser {
  17. /** @var XMLParser the parser to use */
  18. var $parser;
  19. /** @var array ImportedUsers users to import */
  20. var $usersToImport;
  21. /** @var array ImportedUsers imported users */
  22. var $importedUsers;
  23. /** @var array error messages that occurred during import */
  24. var $errors;
  25. /** @var int the ID of the journal to import users into */
  26. var $journalId;
  27. /**
  28. * Constructor.
  29. * @param $journalId int assumed to be a valid journal ID
  30. */
  31. function UserXMLParser($journalId) {
  32. $this->parser = new XMLParser();
  33. $this->journalId = $journalId;
  34. }
  35. /**
  36. * Parse an XML users file into a set of users to import.
  37. * @param $file string path to the XML file to parse
  38. * @return array ImportedUsers the collection of users read from the file
  39. */
  40. function &parseData($file) {
  41. $roleDao =& DAORegistry::getDAO('RoleDAO');
  42. $success = true;
  43. $this->usersToImport = array();
  44. $tree = $this->parser->parse($file);
  45. $journalDao =& DAORegistry::getDAO('JournalDAO');
  46. $journal =& $journalDao->getJournal($this->journalId);
  47. $journalPrimaryLocale = Locale::getPrimaryLocale();
  48. $site =& Request::getSite();
  49. $siteSupportedLocales = $site->getSupportedLocales();
  50. if ($tree !== false) {
  51. foreach ($tree->getChildren() as $user) {
  52. if ($user->getName() == 'user') {
  53. // Match user element
  54. $newUser = new ImportedUser();
  55. foreach ($user->getChildren() as $attrib) {
  56. switch ($attrib->getName()) {
  57. case 'username':
  58. // Usernames must be lowercase
  59. $newUser->setUsername(strtolower($attrib->getValue()));
  60. break;
  61. case 'password':
  62. $newUser->setMustChangePassword($attrib->getAttribute('change') == 'true'?1:0);
  63. $encrypted = $attrib->getAttribute('encrypted');
  64. if (isset($encrypted) && $encrypted !== 'plaintext') {
  65. $ojsEncryptionScheme = Config::getVar('security', 'encryption');
  66. if ($encrypted != $ojsEncryptionScheme) {
  67. $this->errors[] = Locale::translate('plugins.importexport.users.import.encryptionMismatch', array('importHash' => $encrypted, 'ojsHash' => $ojsEncryptionScheme));
  68. }
  69. $newUser->setPassword($attrib->getValue());
  70. } else {
  71. $newUser->setUnencryptedPassword($attrib->getValue());
  72. }
  73. break;
  74. case 'salutation':
  75. $newUser->setSalutation($attrib->getValue());
  76. break;
  77. case 'first_name':
  78. $newUser->setFirstName($attrib->getValue());
  79. break;
  80. case 'middle_name':
  81. $newUser->setMiddleName($attrib->getValue());
  82. break;
  83. case 'last_name':
  84. $newUser->setLastName($attrib->getValue());
  85. break;
  86. case 'initials':
  87. $newUser->setInitials($attrib->getValue());
  88. break;
  89. case 'gender':
  90. $newUser->setGender($attrib->getValue());
  91. break;
  92. case 'affiliation':
  93. $newUser->setAffiliation($attrib->getValue());
  94. break;
  95. case 'email':
  96. $newUser->setEmail($attrib->getValue());
  97. break;
  98. case 'url':
  99. $newUser->setUrl($attrib->getValue());
  100. break;
  101. case 'phone':
  102. $newUser->setPhone($attrib->getValue());
  103. break;
  104. case 'fax':
  105. $newUser->setFax($attrib->getValue());
  106. break;
  107. case 'mailing_address':
  108. $newUser->setMailingAddress($attrib->getValue());
  109. break;
  110. case 'country':
  111. $newUser->setCountry($attrib->getValue());
  112. break;
  113. case 'signature':
  114. $locale = $attrib->getAttribute('locale');
  115. if (empty($locale)) $locale = $journalPrimaryLocale;
  116. $newUser->setInterests($attrib->getValue(), $locale);
  117. break;
  118. case 'interests':
  119. $locale = $attrib->getAttribute('locale');
  120. if (empty($locale)) $locale = $journalPrimaryLocale;
  121. $newUser->setInterests($attrib->getValue(), $locale);
  122. break;
  123. case 'biography':
  124. $locale = $attrib->getAttribute('locale');
  125. if (empty($locale)) $locale = $journalPrimaryLocale;
  126. $newUser->setBiography($attrib->getValue(), $locale);
  127. break;
  128. case 'locales':
  129. $locales = array();
  130. foreach (explode(':', $attrib->getValue()) as $locale) {
  131. if (Locale::isLocaleValid($locale) && in_array($locale, $siteSupportedLocales)) {
  132. array_push($locales, $locale);
  133. }
  134. }
  135. $newUser->setLocales($locales);
  136. break;
  137. case 'role':
  138. $roleType = $attrib->getAttribute('type');
  139. if ($this->validRole($roleType)) {
  140. $role = new Role();
  141. $role->setRoleId($roleDao->getRoleIdFromPath($roleType));
  142. $newUser->addRole($role);
  143. }
  144. break;
  145. }
  146. }
  147. array_push($this->usersToImport, $newUser);
  148. }
  149. }
  150. }
  151. return $this->usersToImport;
  152. }
  153. /**
  154. * Import the parsed users into the system.
  155. * @param $sendNotify boolean send an email notification to each imported user containing their username and password
  156. * @param $continueOnError boolean continue to import remaining users if a failure occurs
  157. * @return boolean success
  158. */
  159. function importUsers($sendNotify = false, $continueOnError = false) {
  160. $success = true;
  161. $this->importedUsers = array();
  162. $this->errors = array();
  163. $userDao =& DAORegistry::getDAO('UserDAO');
  164. $roleDao =& DAORegistry::getDAO('RoleDAO');
  165. if ($sendNotify) {
  166. // Set up mail template to send to added users
  167. import('mail.MailTemplate');
  168. $mail = new MailTemplate('USER_REGISTER');
  169. $journalDao =& DAORegistry::getDAO('JournalDAO');
  170. $journal =& $journalDao->getJournal($this->journalId);
  171. $mail->setFrom($journal->getSetting('contactEmail'), $journal->getSetting('contactName'));
  172. }
  173. for ($i=0, $count=count($this->usersToImport); $i < $count; $i++) {
  174. $user =& $this->usersToImport[$i];
  175. // If the email address already exists in the system,
  176. // then assign the user the username associated with that email address.
  177. if ($user->getEmail() != null) {
  178. $emailExists = $userDao->getUserByEmail($user->getEmail(), true);
  179. if ($emailExists != null) {
  180. $user->setUsername($emailExists->getUsername());
  181. }
  182. }
  183. if ($user->getUsername() == null) {
  184. $newUsername = true;
  185. $this->generateUsername($user);
  186. } else {
  187. $newUsername = false;
  188. }
  189. if ($user->getUnencryptedPassword() != null) {
  190. $user->setPassword(Validation::encryptCredentials($user->getUsername(), $user->getUnencryptedPassword()));
  191. } else if ($user->getPassword() == null) {
  192. $this->generatePassword($user);
  193. }
  194. if (!$newUsername) {
  195. // Check if user already exists
  196. $userExists = $userDao->getUserByUsername($user->getUsername(), true);
  197. if ($userExists != null) {
  198. $user->setId($userExists->getId());
  199. }
  200. } else {
  201. $userExists = false;
  202. }
  203. if ($newUsername || !$userExists) {
  204. // Create new user account
  205. // If the user's username was specified in the data file and
  206. // the username already exists, only the new roles are added for that user
  207. if (!$userDao->insertUser($user)) {
  208. // Failed to add user!
  209. $this->errors[] = sprintf('%s: %s (%s)',
  210. Locale::translate('manager.people.importUsers.failedToImportUser'),
  211. $user->getFullName(), $user->getUsername());
  212. if ($continueOnError) {
  213. // Skip to next user
  214. $success = false;
  215. continue;
  216. } else {
  217. return false;
  218. }
  219. }
  220. }
  221. // Enroll user in specified roles
  222. // If the user is already enrolled in a role, that role is skipped
  223. foreach ($user->getRoles() as $role) {
  224. $role->setUserId($user->getId());
  225. $role->setJournalId($this->journalId);
  226. if (!$roleDao->roleExists($role->getJournalId(), $role->getUserId(), $role->getRoleId())) {
  227. if (!$roleDao->insertRole($role)) {
  228. // Failed to add role!
  229. $this->errors[] = sprintf('%s: %s - %s (%s)',
  230. Locale::translate('manager.people.importUsers.failedToImportRole'),
  231. $role->getRoleName(),
  232. $user->getFullName(), $user->getUsername());
  233. if ($continueOnError) {
  234. // Continue to insert other roles for this user
  235. $success = false;
  236. continue;
  237. } else {
  238. return false;
  239. }
  240. }
  241. }
  242. }
  243. if ($sendNotify && !$userExists) {
  244. // Send email notification to user as if user just registered themselves
  245. $mail->addRecipient($user->getEmail(), $user->getFullName());
  246. $mail->sendWithParams(array(
  247. 'username' => $user->getUsername(),
  248. 'password' => $user->getUnencryptedPassword() == null ? '-' : $user->getUnencryptedPassword(),
  249. 'userFullName' => $user->getFullName()
  250. ));
  251. $mail->clearRecipients();
  252. }
  253. array_push($this->importedUsers, $user);
  254. }
  255. return $success;
  256. }
  257. /**
  258. * Return the set of parsed users.
  259. * @return array ImportedUsers
  260. */
  261. function &getUsersToImport() {
  262. return $this->usersToImport;
  263. }
  264. /**
  265. * Specify the set of parsed users.
  266. * @param $usersToImport ImportedUsers
  267. */
  268. function setUsersToImport($users) {
  269. $this->usersToImport = $users;
  270. }
  271. /**
  272. * Return the set of users who were successfully imported.
  273. * @return array ImportedUsers
  274. */
  275. function &getImportedUsers() {
  276. return $this->importedUsers;
  277. }
  278. /**
  279. * Return an array of error messages that occurred during the import.
  280. * @return array string
  281. */
  282. function &getErrors() {
  283. return $this->errors;
  284. }
  285. /**
  286. * Check if a role type value identifies a valid role that can be imported.
  287. * Note we do not allow users to be imported into the "admin" role.
  288. * @param $roleType string
  289. * @return boolean
  290. */
  291. function validRole($roleType) {
  292. return isset($roleType) && in_array($roleType, array('manager', 'editor', 'sectionEditor', 'layoutEditor', 'reviewer', 'copyeditor', 'proofreader', 'author', 'reader', 'subscriptionManager'));
  293. }
  294. /**
  295. * Generate a unique username for a user based on the user's name.
  296. * @param $user ImportedUser the user to be modified by this function
  297. */
  298. function generateUsername(&$user) {
  299. $userDao =& DAORegistry::getDAO('UserDAO');
  300. $baseUsername = String::regexp_replace('/[^A-Z0-9]/i', '', $user->getLastName());
  301. if (empty($baseUsername)) {
  302. $baseUsername = String::regexp_replace('/[^A-Z0-9]/i', '', $user->getFirstName());
  303. }
  304. if (empty($username)) {
  305. // Default username if we can't use the user's last or first name
  306. $baseUsername = 'user';
  307. }
  308. for ($username = $baseUsername, $i=1; $userDao->userExistsByUsername($username, true); $i++) {
  309. $username = $baseUsername . $i;
  310. }
  311. $user->setUsername($username);
  312. }
  313. /**
  314. * Generate a random password for a user.
  315. * @param $user ImportedUser the user to be modified by this function
  316. */
  317. function generatePassword(&$user) {
  318. $password = Validation::generatePassword();
  319. $user->setUnencryptedPassword($password);
  320. $user->setPassword(Validation::encryptCredentials($user->getUsername(), $password));
  321. }
  322. }
  323. /**
  324. * Helper class representing a user imported from a user data file.
  325. */
  326. import('user.User');
  327. class ImportedUser extends User {
  328. /** @var array Roles of this user */
  329. var $roles;
  330. /**
  331. * Constructor.
  332. */
  333. function ImportedUser() {
  334. $this->roles = array();
  335. parent::User();
  336. }
  337. /**
  338. * Set the unencrypted form of the user's password.
  339. * @param $unencryptedPassword string
  340. */
  341. function setUnencryptedPassword($unencryptedPassword) {
  342. $this->setData('unencryptedPassword', $unencryptedPassword);
  343. }
  344. /**
  345. * Get the user's unencrypted password.
  346. * @return string
  347. */
  348. function getUnencryptedPassword() {
  349. return $this->getData('unencryptedPassword');
  350. }
  351. /**
  352. * Add a new role to this user.
  353. * @param $role Role
  354. */
  355. function addRole(&$role) {
  356. array_push($this->roles, $role);
  357. }
  358. /**
  359. * Get this user's roles.
  360. * @return array Roles
  361. */
  362. function &getRoles() {
  363. return $this->roles;
  364. }
  365. }
  366. ?>