User.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <?php
  2. namespace app\models;
  3. use \MongoDate;
  4. use \lithium\util\String;
  5. use \lithium\util\Validator;
  6. use \App\Libraries\openID\LightOpenID;
  7. use \lithium\security\Password;
  8. class User extends \lithium\data\Model {
  9. public $hasMany = array('Post', 'Friends' => array('keys' => array('id' => 'ToUserId')));
  10. public static function __init()
  11. {
  12. //Initialize the parent if you want the database and everything setup (which of course we do)
  13. parent::__init();
  14. //Confirms that the username isn't already in use.
  15. Validator::add('isUniqUser', function($username) {
  16. //If we can't find a user with the same user name then the name is unique.
  17. return User::count(array('conditions' => compact('username'))) == 0;
  18. });
  19. //Checks if the username contains profanity
  20. Validator::add('isClean', function($username) {
  21. //Needs to do a dictonary lookup, but too lazy to implement right now.
  22. return true;
  23. });
  24. Validator::add('isValidGender', function($gender) {
  25. //If the geneder is male or female return true.
  26. return ($gender == 'Male' || $gender == 'Female');
  27. });
  28. Validator::add('isUniqueEmail', function($email) {
  29. //Find all the email address that match the one inputted,
  30. //If there is none found (count == 0) then return true (Email address is unique)
  31. return User::count(array('conditions' => compact('email'))) == 0;
  32. });
  33. Validator::add('validBirthday', function($birthday) {
  34. // :TODO:
  35. //*birthday needs to be 1930 <= $birthday <= current year - 11 (11 or older);
  36. return true;
  37. });
  38. }
  39. /* Validation code */
  40. /*
  41. Things that need to be validated
  42. *The username cannot be taken
  43. *the username cannot cotain special chars or spaces
  44. *there must be an email address
  45. *The email address needs to be a valid email
  46. *it cannot be in use already
  47. *the password needs to be atleast 6 characters
  48. *the username cannot contain profanity
  49. *birthday needs to be 1930 <= $birthday <= current year - 11 (11 or older);
  50. *gender must be Male or Female
  51. */
  52. public $validates = array(
  53. 'username' => array(array('isUniqUser', 'message' => "Username is already taken."),
  54. array('notEmpty', 'message' => 'Please enter a Username.'),
  55. array('isClean', 'message' => 'Profanity is not allowed in Usernames'),
  56. array('alphaNumeric', 'message' => "Usernames cant contain special characters")
  57. ),
  58. 'email' => array(array('email', 'message' => 'The email address is not valid.'),
  59. array('notEmpty', 'message' => 'An email address must be entered.'),
  60. array('isUniqueEmail', 'message' => 'That email address is already in use. Did you forget your password?')
  61. ) /*,
  62. 'newpass' => array(array('lengthBetween' => array('min' => '6', 'max' =>'20'),
  63. 'message' => 'Your password must be between 6 and 20 characters')
  64. )*/ /*,
  65. //It's always possible for people to submit invalid data using cURL or something.
  66. 'gender' => array('isValidGender', 'message' => 'Please check for dangly bits or lack thereof.')
  67. */
  68. );
  69. /* Defaults */
  70. /*
  71. joindate = today,
  72. accesslevel = "user"
  73. */
  74. /**
  75. * Creates a post and stores it into the appropriate user(s) array(s)
  76. * @param User $entity the instance of the user posting the message
  77. * @param Array $data The data from the request (usually submiited from the form)
  78. * @param Array $options Currently not implemented
  79. * @return null Nothing for now, though should return true or false in the future :TODO:
  80. */
  81. public function post($entity, $data, array $options = array())
  82. {
  83. //TODO, fix all methods so that they don't take $data directly
  84. //TODO add validators to these methods/models
  85. //Create the post
  86. $post = Post::create(array(//'datetime' => new MongoDate(),
  87. 'username' => $entity->username,
  88. 'user_id' => $entity->id,
  89. 'level' => null));
  90. //1. Parse
  91. //Break the string into an array of words
  92. $search = explode(" ", $data['body']);
  93. //if the first word is DM
  94. if ($search[0] == "DM")
  95. {
  96. //Remove the '@' symbol before we search for that username
  97. $to = substr($search[1], 1);
  98. $post->type = "DM";
  99. //:TODO: Catch the return incase it's false.
  100. return $post->directMessage($to);
  101. }
  102. //If the post beings with a mention (it's a reply / note)
  103. if ($search[0] == "@")
  104. {
  105. //Set the post level to hidden
  106. $post->level = "hidden";
  107. }
  108. //Check if there are any mentions or topics
  109. $post->body = $post->parse($search);
  110. //Because there is a chance that parse will set post level to something
  111. //We pass the current value to level since it will just
  112. //return the same it not set.
  113. //Yes, we could use an if ! null but whatever.
  114. $post->level = $this->postLevel($entity, $post, $post->level);
  115. //Save the post to the posts database.
  116. $post->save();
  117. }
  118. /**
  119. * Returns the appropriate post level for the post
  120. * @see app\models\Post
  121. * @param User $user The user instance of the user that the post will be posted to
  122. * @param Post $post The Post to determine the level for
  123. * @param string $level The level (if you want to override the output)
  124. * @return string $level if one is passed in, otherwise hidden if the post begins with a mention or private if the user has his posts protected
  125. */
  126. public static function postLevel($user, $post, $level = null)
  127. {
  128. //if for some crazy reason you need to set the post to a specific type using this
  129. // method then if $level is not null, return $level
  130. if ($level != null)
  131. {
  132. return $level;
  133. }
  134. //If the post is directed at user (begins with @username)
  135. //This is done in parse right now
  136. //return "hidden"
  137. //If the user has their post set to private
  138. if (isset($user->settings['private']));
  139. {
  140. //return private
  141. return "private";
  142. }
  143. //If none of the above apply
  144. return "public";
  145. }
  146. //When we switch to a graph database, there is a bidirection vertex function
  147. //So we can cut this search down to one query, and one line of code :P
  148. /**
  149. * Check wether user1 and user2 are friends
  150. *
  151. * @param string $user1 The username of the first user
  152. * @param string $user2 The username of the second user
  153. * @return boolean True if the users are friends, false otherwise
  154. */
  155. public static function areFriends($user1, $user2)
  156. {
  157. //Get the first user from the database,
  158. $usr1 = User::find('first', array('conditions' => array('username' => $user1)));
  159. //If user 2 is in user1's friends,
  160. if (in_array($user2, $usr1->friends))
  161. {
  162. $usr2 = User::find('first', array('conditions' => array('username' => $user2)));
  163. //And user1 is in user2s friends
  164. if (in_array($user1, $usr2->friends))
  165. {
  166. return true;
  167. }
  168. }
  169. //otherwise
  170. return false;
  171. }
  172. /**
  173. * GetPosts gets posts from the user (entity) based on some params, and returns them
  174. * @param User $entity, the calling object
  175. * @param Array $options, the options that will be used, you can see the defaults below
  176. * @return array(), with all the posts found or false, if somehow that didn't happen
  177. */
  178. public function getPosts($entity, array $options = array())
  179. {
  180. $posts;
  181. $defaults = array(
  182. 'limit' => '20',
  183. 'qualifier' => 'all',
  184. 'level' => 'public',
  185. );
  186. //If the user passed in options
  187. return $posts;
  188. }
  189. public function myFriends($entity)
  190. {
  191. return self::find(array('conditions' => array('id' => $entity->friends->map(function ($f) { return $f->FromUserId;}))));
  192. //return static::FindAllById($entity->friends->map(function ($f) { return $f->FromUserId; }));
  193. }
  194. //Overrides save so we can do some stuff before the data is commited to the database.
  195. public function save($entity, $data = null, array $options = array())
  196. {
  197. //If the new password field is empty, or this is a new user
  198. if(!empty($entity->newpass) || !$entity->exists())
  199. {
  200. //Generate Salt for the user.
  201. $salt = Password::salt('bf', 6);
  202. //Hash their password.
  203. $data['password'] = Password::hash($entity->newpass, $salt);
  204. $data['pepper'] = $salt;
  205. unset($entity->newpass);
  206. }
  207. //If the entity doesn't exist or if the password password has been modified
  208. return parent::save($entity, $data, $options);
  209. }
  210. }
  211. ?>