diff options
author | Michael Francis <edude03@gmail.com> | 2011-05-28 13:28:16 -0400 |
---|---|---|
committer | Michael Francis <edude03@gmail.com> | 2011-05-28 13:28:16 -0400 |
commit | 2389d66da849798f8d4ec5f10e3b07c11da49185 (patch) | |
tree | e22556d12982395b469a23420c662662e3e064cc /models/User.php | |
download | otakuhub-2389d66da849798f8d4ec5f10e3b07c11da49185.tar.xz |
Initial Commit
Diffstat (limited to 'models/User.php')
-rw-r--r-- | models/User.php | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/models/User.php b/models/User.php new file mode 100644 index 0000000..20c102a --- /dev/null +++ b/models/User.php @@ -0,0 +1,347 @@ +<?php + +namespace app\models; + +use \MongoDate; +use \lithium\util\String; +use \lithium\util\Validator; +use \App\Libraries\openID\LightOpenID; + +class User extends \lithium\data\Model { + //To bypass mongo bug + protected $_meta = array('key' => '_id'); + protected $_schema = array('_id' => array('type' => 'id'), 'feed' => array('type'=>'string', 'array'=>true)); + + public static function __init() + { + //Initialize the parent if you want the database and everything setup (which of course we do) + parent::__init(); + + //Confirms that the username isn't already in use. + Validator::add('isUniqUser', function($username) { + //If we can't find a user with the same user name then the name is unique. + return User::count(array('conditions' => compact('username'))) == 0; + }); + + //Checks if the username contains profanity + Validator::add('isClean', function($username) { + //Needs to do a dictonary lookup, but too lazy to implement right now. + return true; + }); + + Validator::add('isValidGender', function($gender) { + //If the geneder is male or female return true. + return ($gender == 'Male' || $gender == 'Female'); + }); + + Validator::add('isUniqueEmail', function($email) { + //Find all the email address that match the one inputted, + //If there is none found (count == 0) then return true (Email address is unique) + return User::count(array('conditions' => compact('email'))) == 0; + }); + + Validator::add('validBirthday', function($birthday) { + // :TODO: + //*birthday needs to be 1930 <= $birthday <= current year - 11 (11 or older); + return true; + }); + } + + + /* Validation code */ + /* + Things that need to be validated + *The username cannot be taken + *the username cannot cotain special chars or spaces + *there must be an email address + *The email address needs to be a valid email + *it cannot be in use already + *the password needs to be atleast 6 characters + *the username cannot contain profanity + *birthday needs to be 1930 <= $birthday <= current year - 11 (11 or older); + *gender must be Male or Female + */ + public $validates = array( + 'username' => array(array('isUniqUser', 'message' => "Username is already taken."), + array('notEmpty', 'message' => 'Please enter a Username.'), + array('isClean', 'message' => 'Profanity is not allowed in Usernames'), + array('alphaNumeric', 'message' => "Usernames cant contain special characters") + ), + + 'email' => array(array('email', 'message' => 'The email address is not valid.'), + array('notEmpty', 'message' => 'An email address must be entered.'), + array('isUniqueEmail', 'message' => 'That email address is already in use. Did you forget your password?') + ), + + + //Passwords validation is invented. + 'password' => array(array('lengthBetween' =>array('min' => '6', 'max' =>'20'), + 'message' => 'Your password must be between 6 and 20 characters') + ) /*, + + //It's always possible for people to submit invalid data using cURL or something. + 'gender' => array('isValidGender', 'message' => 'Please check for dangly bits or lack thereof.') + */ + ); + + + /* Defaults */ + /* + joindate = today, + accesslevel = "user" + */ + + public function updateuser($entity, $data) + { + $conditions = array('_id' => $entity->_id, 'state' => 'default'); + $options = array('multiple' => false, 'safe' => true, 'upsert'=>true); + return static::update($data, $conditions, $options); + } + + /** + * Creates a post and stores it into the appropriate user(s) array(s) + * @param User $entity the instance of the user posting the message + * @param Array $data The data from the request (usually submiited from the form) + * @param Array $options Currently not implemented + * @return null Nothing for now, though should return true or false in the future :TODO: + */ + public function post($entity, $data, array $options = array()) + { + //TODO, fix all methods so that they don't take $data directly + //TODO add validators to these methods/models + + //Create the post + $post = Post::create(array('datetime' => new MongoDate(), + 'username' => $entity->username, + 'user_id' => $entity->_id, + 'level' => null)); + //1. Parse + //Break the string into an array of words + $search = explode(" ", $data['body']); + + //if the first word is DM + if ($search[0] == "DM") + { + //Remove the '@' symbol before we search for that username + $to = substr($search[1], 1); + + $post->type = "DM"; + //:TODO: Catch the return incase it's false. + return $post->directMessage($to); + } + + //If the post beings with a mention (it's a reply / note) + if ($search[0] == "@") + { + //Set the post level to hidden + $post->level = "hidden"; + } + + + //Check if there are any mentions or topics + $post->body = $post->parse($search); + + + //Because there is a chance that parse will set post level to something + //We pass the current value to level since it will just + //return the same it not set. + //Yes, we could use an if ! null but whatever. + $post->level = $this->postLevel($entity, $post, $post->level); + + //Save the post to the posts database. + $post->save(); + + //If the user has friends + if (count($entity->friends) > 0) + { + //Save this posts to the feed of all the Users Friends + $post->storeAll($entity->friends); + } + //Add this post to the user's feed array + $post->store($entity); + + + + + //$save = $entity->save(null, array('validate' => false)); + /* In the future, there should be a way to make this method quicker and non-blocking*/ + //For each friend, post it in their feed (friends is an array of usernames as strings) + /*if (!empty($entity->friends)) + { + foreach ($entity->friends as $friend) + { + //Grab the friend from the database + $curFriend = User::find('first', array('conditions' => array('username' => $friend))); + + //Add the post to their feed. + //Array unshift puts the new post at the first element of the feed array. + $curFriend->feed = array_unshift($post->_id, $curFriend->feed); + + //Save the friend to the database, + $curFriend->save(array('validates' => false)); + + //Eventually, we can call a node.js endpoint here + //To tell all subscribers that there is a new a post + //Something like "curl POST $post->_id nodeserver://endpoint/myFeed" + } + } */ + } + + /** + * Store's the post to the specified user's feed + * @param User $user The user to add the post to + * @param Post $post The post too add to the feed + * @return boolean True if the operation sucsceeded, false otherwise + */ + private function storePost($user, $post) + { + $updateData = array('$push' => array('feed' => $post['_id']->__toString())); + $conditions = array('_id' => $user['_id']); + $result = User::update($updateData, $conditions, array('atomic' => false)); + + return $result; + } + + + /** + * Returns the appropriate post level for the post + * @see app\models\Post + * @param User $user The user instance of the user that the post will be posted to + * @param Post $post The Post to determine the level for + * @param string $level The level (if you want to override the output) + * @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 + */ + public static function postLevel($user, $post, $level = null) + { + //if for some crazy reason you need to set the post to a specific type using this + // method then if $level is not null, return $level + if ($level != null) + { + return $level; + } + //If the post is directed at user (begins with @username) + //This is done in parse right now + //return "hidden" + + //If the user has their post set to private + if (isset($user->settings['private'])); + { + //return private + return "private"; + } + + //If none of the above apply + return "public"; + } + + //When we switch to a graph database, there is a bidirection vertex function + //So we can cut this search down to one query, and one line of code :P + /** + * Check wether user1 and user2 are friends + * + * @param string $user1 The username of the first user + * @param string $user2 The username of the second user + * @return boolean True if the users are friends, false otherwise + */ + public static function areFriends($user1, $user2) + { + //Get the first user from the database, + $usr1 = User::find('first', array('conditions' => array('username' => $user1))); + + //If user 2 is in user1's friends, + if (in_array($user2, $usr1->friends)) + { + $usr2 = User::find('first', array('conditions' => array('username' => $user2))); + //And user1 is in user2s friends + if (in_array($user1, $usr2->friends)) + { + return true; + } + } + //otherwise + return false; + } + + /** + * GetPosts gets posts from the user (entity) based on some params, and returns them + * @param User $entity, the calling object + * @param Array $options, the options that will be used, you can see the defaults below + * @return array(), with all the posts found or false, if somehow that didn't happen + */ + public function getPosts($entity, array $options = array()) + { + $posts; + $defaults = array( + 'limit' => '20', + 'qualifier' => 'all', + 'level' => 'public', + ); + + //If the user passed in options + if (!empty($options)) + { + //merge the options with the defaults (upsert them) + array_merge($defaults, $options); + } + + //var_dump($entity); + //exit(); + //If the user has more posts than the limit, return the limit, if the have less return + $count = (count($entity->feed) >= $defaults['limit']) ? $defaults['limit'] : count($entity->feed); + if ($count == 0) + { + return false; + } + //else + var_dump(Post::find('all', array('conditions' => array('$in' => $entity->feed)))); + exit(); + for ($i = 0; $i < $count; $i++) + { + $posts[] = Post::find('all', array('conditions' => array('$in' => $entity->feed))); + $posts[] = Post::find($qaulifier, array('conditions' => array('_id' => $entity->feed[$i], 'level' => $defaults[level]))); + } + return $posts; + } + + /** + * Increments the amount profile views for the user. + * This is the command we are going to give to Mongo, which breaks down to db.users.update({_id : $id}, {$inc: {profileViews : 1}} ) + * Which says, find the user by their mongo ID, then increment their profile views by one. + * @param User $entity The instance of user to increment + * @param string $type Not implemented but in the future will allow you to increment anime manga and kdrama list views :TODO: + * @return null + */ + public function incrementViews($entity, $type = null) + { + if ($type = null) + { + $views = 'profileViews'; + } + $updateData = array('$inc' => array('profileViews' => 1)); + $conditions = array('_id' => $entity['_id']); + $result = User::update($updateData, $conditions, array('atomic' => false)); + return $result; + + } + + + //Overrides save so we can do some stuff before the data is commited to the database. + public function save($entity, $data = null, array $options = array()) + { + //If the new password field is empty, or this is a new user + if(!empty($entity->newpass) || !$entity->exists()) + { + //Generate Salt for the user. + $salt = String::genSalt('bf', 6); + + //Hash their password. + $data['password'] = String::hashPassword($entity->newpass, $salt); + $data['salt'] = $salt; + unset($entity->newpass); + } + //If the entity doesn't exist or if the password password has been modified + return parent::save($entity, $data, $options); + } +} + +?>
\ No newline at end of file |