PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/member.symphony.php

https://github.com/ophentis/members
PHP | 367 lines | 214 code | 65 blank | 88 comment | 64 complexity | b9edd67f2db1724b6be3f234cdbba462 MD5 | raw file
  1. <?php
  2. Class SymphonyMember extends Members {
  3. public function __construct($driver) {
  4. parent::__construct($driver);
  5. }
  6. /*-------------------------------------------------------------------------
  7. Utilities:
  8. -------------------------------------------------------------------------*/
  9. /**
  10. * This function determines what field instance to use based on the current
  11. * $_POST data.
  12. *
  13. * @param array $credentials
  14. * @param boolean $simplified
  15. * If true, this function assumes that the $credentials array contains a
  16. * username and email key, otherwise, it will attempt to map a value using
  17. * the field handles to a normalised username/email.
  18. * @return Field
  19. */
  20. public static function setIdentityField(array $credentials, $simplified = true) {
  21. if($simplified) {
  22. extract($credentials);
  23. }
  24. else {
  25. // Map POST data to simple terms
  26. if(isset($credentials[extension_Members::getFieldHandle('identity')])) {
  27. $username = $credentials[extension_Members::getFieldHandle('identity')];
  28. }
  29. if(isset($credentials[extension_Members::getFieldHandle('email')])) {
  30. $email = $credentials[extension_Members::getFieldHandle('email')];
  31. }
  32. }
  33. // Check to see if neither can be found, just return null
  34. if(is_null($username) && is_null($email)) {
  35. return null;
  36. }
  37. // If email is supplied, use the Email field
  38. if(!is_null($email) && (isset($email) && !empty($email))) {
  39. $identity_field = extension_Members::getField('email');
  40. }
  41. // If username is supplied, use the Username field
  42. else if (!is_null($username) && (isset($username) && !empty($username))) {
  43. $identity_field = extension_Members::getField('identity');
  44. }
  45. return $identity_field;
  46. }
  47. /*-------------------------------------------------------------------------
  48. Finding:
  49. -------------------------------------------------------------------------*/
  50. /**
  51. * Returns an Entry object given an array of credentials
  52. *
  53. * @param array $credentials
  54. * @return integer
  55. */
  56. public function findMemberIDFromCredentials(array $credentials) {
  57. extract($credentials);
  58. if((is_null($username) && is_null($email))) return null;
  59. $identity = SymphonyMember::setIdentityField($credentials);
  60. if(!$identity instanceof Field) return null;
  61. // Member from Identity
  62. $member_id = $identity->fetchMemberIDBy($credentials);
  63. // Validate against Password
  64. // It's expected that $password is sha1'd and salted.
  65. $auth = extension_Members::getField('authentication');
  66. if(!is_null($auth)) {
  67. $member_id = $auth->fetchMemberIDBy($credentials, $member_id);
  68. }
  69. // No Member found, can't even begin to check Activation
  70. // Return null
  71. if(is_null($member_id)) return null;
  72. // Check that if there's activiation, that this Member is activated.
  73. if(!is_null(extension_Members::getFieldHandle('activation'))) {
  74. $entry = extension_Members::$entryManager->fetch($member_id);
  75. $isActivated = $entry[0]->getData(extension_Members::getField('activation')->get('id'), true)->activated == "yes";
  76. // If we are denying login for non activated members, lets do so now
  77. if(extension_Members::getField('activation')->get('deny_login') == 'yes' && !$isActivated) {
  78. extension_Members::$_errors[extension_Members::getFieldHandle('activation')] = array(
  79. 'message' => __('Member is not activated.'),
  80. 'type' => 'invalid',
  81. 'label' => extension_Members::getField('activation')->get('label')
  82. );
  83. return null;
  84. }
  85. // If the member isn't activated and a Role field doesn't exist
  86. // just return false.
  87. if(!$isActivated) {
  88. if(is_null(extension_Members::getFieldHandle('role'))) {
  89. extension_Members::$_errors[extension_Members::getFieldHandle('activation')] = array(
  90. 'message' => __('Member is not activated.'),
  91. 'type' => 'invalid',
  92. 'label' => extension_Members::getField('activation')->get('label')
  93. );
  94. return false;
  95. }
  96. }
  97. }
  98. return $member_id;
  99. }
  100. public function fetchMemberFromID($member_id = null) {
  101. $member = parent::fetchMemberFromID($member_id);
  102. if(is_null($member)) return null;
  103. // If the member isn't activated and a Role field exists, we need to override
  104. // the current Role with the Activation Role. This may allow Members to view certain
  105. // things until they active their account.
  106. if(!is_null(extension_Members::getFieldHandle('activation'))) {
  107. if($member->getData(extension_Members::getField('activation')->get('id'), true)->activated != "yes") {
  108. if(!is_null(extension_Members::getFieldHandle('role'))) {
  109. $member->setData(
  110. extension_Members::getField('role')->get('id'),
  111. extension_Members::getField('activation')->get('activation_role_id')
  112. );
  113. }
  114. }
  115. }
  116. return $member;
  117. }
  118. /*-------------------------------------------------------------------------
  119. Authentication:
  120. -------------------------------------------------------------------------*/
  121. /**
  122. * Login function takes an associative array of fields that contain
  123. * an Identity field (Email/Username) and a Password field. They keys
  124. * should be the Field's `element_name`.
  125. * An optional parameter, `$isHashed` refers to if the password provided
  126. * is hashed already, or requires hashing prior to logging in.
  127. *
  128. * @param array $credentials
  129. * @param boolean $isHashed
  130. * Defaults to false, which will encode the password value before attempting
  131. * to log the user in
  132. * @return boolean
  133. */
  134. public function login(array $credentials, $isHashed = false) {
  135. $username = $email = $password = null;
  136. $data = array();
  137. // Map POST data to simple terms
  138. if(isset($credentials[extension_Members::getFieldHandle('identity')])) {
  139. $username = $credentials[extension_Members::getFieldHandle('identity')];
  140. }
  141. if(isset($credentials[extension_Members::getFieldHandle('email')])) {
  142. $email = $credentials[extension_Members::getFieldHandle('email')];
  143. }
  144. // Allow login via username OR email. This normalises the $data array from the custom
  145. // field names to simple names for ease of use.
  146. if(isset($username)) {
  147. $data['username'] = Symphony::Database()->cleanValue($username);
  148. }
  149. else if(isset($email) && !is_null(extension_Members::getFieldHandle('email'))) {
  150. $data['email'] = Symphony::Database()->cleanValue($email);
  151. }
  152. // Map POST data for password to `$password`
  153. if(isset($credentials[extension_Members::getFieldHandle('authentication')])) {
  154. $password = $credentials[extension_Members::getFieldHandle('authentication')];
  155. // Use normalised handles for the fields
  156. if(!empty($password)) {
  157. $data['password'] = $isHashed ? $password : extension_Members::getField('authentication')->encodePassword($password);
  158. }
  159. else {
  160. $data['password'] = '';
  161. }
  162. }
  163. // Check to ensure that we actually have some data to try and log a user in with.
  164. if(empty($data['password']) && isset($credentials[extension_Members::getFieldHandle('authentication')])) {
  165. extension_Members::$_errors[extension_Members::getFieldHandle('authentication')] = array(
  166. 'message' => __('%s is a required field.', array(extension_Members::getField('authentication')->get('label'))),
  167. 'type' => 'missing',
  168. 'label' => extension_Members::getField('authentication')->get('label')
  169. );
  170. }
  171. if(isset($data['username']) && empty($data['username'])) {
  172. extension_Members::$_errors[extension_Members::getFieldHandle('identity')] = array(
  173. 'message' => __('%s is a required field.', array(extension_Members::getField('identity')->get('label'))),
  174. 'type' => 'missing',
  175. 'label' => extension_Members::getField('identity')->get('label')
  176. );
  177. }
  178. if(isset($data['email']) && empty($data['email'])) {
  179. extension_Members::$_errors[extension_Members::getFieldHandle('email')] = array(
  180. 'message' => __('%s is a required field.', array(extension_Members::getField('email')->get('label'))),
  181. 'type' => 'missing',
  182. 'label' => extension_Members::getField('email')->get('label')
  183. );
  184. }
  185. // If there is errors already, no point continuing, return false
  186. if(!empty(extension_Members::$_errors)) {
  187. return false;
  188. }
  189. if($id = $this->findMemberIDFromCredentials($data)) {
  190. try{
  191. self::$member_id = $id;
  192. $this->initialiseCookie();
  193. $this->initialiseMemberObject();
  194. $this->cookie->set('id', $id);
  195. if(isset($username)) {
  196. $this->cookie->set('username', $data['username']);
  197. }
  198. else {
  199. $this->cookie->set('email', $data['email']);
  200. }
  201. $this->cookie->set('password', $data['password']);
  202. self::$isLoggedIn = true;
  203. } catch(Exception $ex){
  204. // Or do something else?
  205. throw new Exception($ex);
  206. }
  207. return true;
  208. }
  209. $this->logout();
  210. return false;
  211. }
  212. public function isLoggedIn() {
  213. if(self::$isLoggedIn) return true;
  214. $this->initialiseCookie();
  215. $data = array(
  216. 'password' => $this->cookie->get('password')
  217. );
  218. if(!is_null($this->cookie->get('username'))) {
  219. $data['username'] = $this->cookie->get('username');
  220. }
  221. else {
  222. $data['email'] = $this->cookie->get('email');
  223. }
  224. if($id = $this->findMemberIDFromCredentials($data)) {
  225. self::$member_id = $id;
  226. self::$isLoggedIn = true;
  227. return true;
  228. }
  229. $this->logout();
  230. return false;
  231. }
  232. /*-------------------------------------------------------------------------
  233. Filters:
  234. -------------------------------------------------------------------------*/
  235. public function filter_LockRole(array &$context) {
  236. // If there is a Role field, this will force it to be the Default Role.
  237. if(!is_null(extension_Members::getFieldHandle('role'))) {
  238. // Can't use `$context` as `$fields` only contains $_POST['fields']
  239. if(isset($_POST['id'])) {
  240. $member = parent::fetchMemberFromID(
  241. Symphony::Database()->cleanValue($_POST['id'])
  242. );
  243. if(!$member instanceof Entry) return;
  244. // If there is a Role set to this Member, lock the `$fields` role to the same value
  245. $role_id = $member->getData(extension_Members::getField('role')->get('id'), true)->role_id;
  246. $context['fields'][extension_Members::getFieldHandle('role')] = $role_id;
  247. }
  248. // New Member, so use the default Role
  249. else {
  250. $context['fields'][extension_Members::getFieldHandle('role')] = extension_Members::getField('role')->get('default_role');
  251. }
  252. }
  253. }
  254. public function filter_LockActivation(array &$context) {
  255. // If there is an Activation field, this will force it to be no.
  256. if(!is_null(extension_Members::getFieldHandle('activation'))) {
  257. // Can't use `$context` as `$fields` only contains $_POST['fields']
  258. if(isset($_POST['id'])) {
  259. $member = parent::fetchMemberFromID(
  260. Symphony::Database()->cleanValue($_POST['id'])
  261. );
  262. if(!$member instanceof Entry) return;
  263. // Lock the `$fields` activation to the same value as what is set to the Member
  264. $activated = $member->getData(extension_Members::getField('activation')->get('id'), true)->activated;
  265. $context['fields'][extension_Members::getFieldHandle('activation')] = $activated;
  266. }
  267. // New Member, so use the default Role
  268. else {
  269. $context['fields'][extension_Members::getFieldHandle('activation')] = 'no';
  270. }
  271. }
  272. }
  273. /**
  274. * Part 1 - Update Password
  275. * If there is an Authentication field, we need to inject the 'optional'
  276. * key so that it won't flag a user's password as invalid if they fail to
  277. * enter it. The use of the 'optional' key will only trigger validation should
  278. * they enter a value in the password field, in which it assumes the user is
  279. * trying to update their password.
  280. */
  281. public function filter_UpdatePassword(array &$context) {
  282. if(!is_null(extension_Members::getFieldHandle('authentication'))) {
  283. $context['fields'][extension_Members::getFieldHandle('authentication')]['optional'] = 'yes';
  284. }
  285. }
  286. /**
  287. * Part 2 - Update Password, logs the user in
  288. * If the user changed their password, we need to login them back into the
  289. * system with their new password.
  290. */
  291. public function filter_UpdatePasswordLogin(array $context) {
  292. // If the user didn't update their password.
  293. if(empty($context['fields'][extension_Members::getFieldHandle('authentication')]['password'])) return;
  294. $this->login(array(
  295. extension_Members::getFieldHandle('authentication') => $context['fields'][extension_Members::getFieldHandle('authentication')]['password'],
  296. extension_Members::getFieldHandle('identity') => $context['entry']->getData(extension_Members::getField('identity')->get('id'), true)->value
  297. ), false);
  298. if(isset($_REQUEST['redirect'])) {
  299. redirect($_REQUEST['redirect']);
  300. }
  301. }
  302. }