array('level' != private))) * However, we need to differentiate posts that are Hidden (posts that begin with a @username), Friends only (set by user) or * Public (by default all posts.) there should be a method that filters the new post method, that takes a post, determines * what access level it should be then passes that back to the calling method (in save?) * * Of course, for logged in users, we need to do a multiselect I guess, something like find posts where access level is hidden * friends only, and public, ordered by date (descending) limit 20 or so (use pagination plugin) * * Finally, there should be an an option to make all posts private, this can be done by the postlevel() method, it can check if * the user has the private option set, then if true return private for all posts :) */ public function index($username = null) { //If no username was entered, if ($username == null) { //Show a user list? // TODO: Pagination //Show a list of all users $users = User::all(); return compact('users'); //maybe we can use the endpoint hook and show a "network activity feed" //For example show all public posts as they get posted using ajax ? //Maybe we should have a route for this? /activity maybe? } //Otherwise get that user $user = User::find('first', array('conditions' => compact('username'))); //find all posts, sort by date, order descending, limit to 20 $feed; //Dont know if php will keep counts return on the stack so I'm storing it to avoid calling it 3 times. $tmpCount = count($user->feed); //If the user has 20 or more posts then query 20, otherwise query the number of posts the user has $count = ($tmpCount >= 20) ? 20 : $tmpCount; //If the user is logged in $user = Auth::check('default'); if ($user) { if ($user->username == $username) { $feed = $user->getPosts(array('level' => null)); return compact($feed, $user); } //if the user is logged in and the users are friends if (User::areFriend(Auth::check('default'), $user)) { $feed = $user->getPosts(array('level' => null)); return compact($feed, $user); } } //If they aren't friend, or if the user isn't logged in it defaults to the public version (filter private posts) //If the user isn't logged in, then we should show a signup partial like twitter else { //find all non-private posts, limit 20, order descending (decending was taken care of with array_unshift btw) $feed = $user->getPost(array('level' => array('$ne' => "private"))); return compact($feed, $user); } } /** * How this method should work: * Since this network is default open like twitter, there is three types of relationships: * 1) Mutually Oblivious: Neither user knows each other. * 2) You Follow: You follow a user and sees their non-private posts * 3) Friends: being friends allows you to see each others privates posts * (@see app\models\post) for an example of how this works * * Now, for now there are two types of requests: Friend requests which causes both users to automatically follow eachother * And follows. Follows are unidirectional and thus don't require the followees permission */ public function follow($username = null) { $status; $message; if($this->request->data) { $user = Auth::check('default'); if ($user) { $user = User::find('first', array('conditions' => array('username' => $user['username']))); if ($user->follow($username)) { $status = true; return array('sucseeded' => true, 'message' => 'You are now following $username'); } } } } /** * Calls the user to addFriend method, then returns the status. * @param username The name of the user to add as a friend */ public function addfriend($username = null) { } public function reconfirm() { //Search the database for email address if (ConfirmKey::count(array('conditions' => array('email' => $this->request->data['email']))) != 0) { //Resend the confirmation email } else { //Show them a message } //Send a new key } public function profile($username) { //If no username is passed in. if (empty($username)) { $this->redirect('/'); } //Otherwise else { //Find that user, and go to their profile page. $user = User::find('first', array('conditions' => compact('username'))); //$photo = (empty($user->profilepic) ? ProfilePic::create() : $user->profilepic); return compact('user', 'photo'); //Render the profile layout } } public function post() { if ($this->request->data) { $user = Auth::check('default'); if ($user) { $user = User::find($user['id']); $user->post($this->request->data); } /* :TODO: Need to return a status here */ $this->redirect('Users::feed'); } } public function feed() { //Get the currently logged in user $user = Auth::check('default'); //If there is a user logged in (There should be since feed isn't a public function) if ($user) { //Get that user from the database $user = User::find('first', array('conditions' => array('username' => $user['username']))); //Set the feed variable scope (since we are going to use it outside the loop) $feed; if (isset($user->feed)) { //For each post ID in $users feed, foreach ($user->feed as $post) { //Find the post by it's ID $post = Post::find($post); //If a post was found, if (!empty($post)) { //Add it to the feed $feed[] = $post; } //Else we should remove the the ID from the users feed. } /* new posts are appended to the end of the feed array, therefore new posts naturally end up at the bottom of the feed * therefore, we reverse the order of the array so that new posts end up at the top of the feed. * This is probably faster than doing sorting by date at the database level, though it for some reason * posts don't get inserted in the right order it could cause them to come out wrong in the view */ $feed = array_reverse($feed); //This renders a custom layout we use for the feed, then passes user and feed to the view for the variables. } return compact('user', 'feed'); } } /* If the user is valid, but not confirmed, tell the user they haven't confirmed, offer to resend the confirmation email or changed their email address. */ public function login($location = null, $args = null) { if (!empty($this->request->data)) { $user = Auth::check('default', $this->request); if ($user) { $user = User::find('first', array('conditions' => array('username' => $user['username']))); $user->lastLogin = date('Y-m-d H:i:s', time()); $user->save(null, array('validate' => false)); //If the user hasn't confirmed their account if(!$user->confirmed) { //Redirect them to the confirmation page. return $this->redirect('Signup::confirm'); } //If the user's account is not active they are probably banned if (!$user->active) { return $this->redirect('/pages/banned'); } //If the user was trying to go somewhere, redirect them there $loc = Session::read('url'); if (isset($loc)) { Session::delete('url'); return $this->redirect(array('controller' => $loc['controller'], 'action' => $loc['action'], 'args' => $loc['args'] )); } //Otherwise send them to the hompa return $this->redirect('Users::feed'); } else { FlashMessage::write('Username or Password Incorrect.'); } } } //Logout public function logout() { //If the user logs out //Clear their auth cookie Auth::Clear('default'); //Redirect them to the homepage. return $this->redirect('/'); } public function changePassword() { //Get the user to verify their current password $input = $this->request->data; //If there is inputfrom the form if ($input) { //Get the user from auth $user = Auth::check('default'); //Ensure that the passwords are the same. if ($input['newpass'] != $input['confirm']) { //return error return $this->redirect('/'); } else if(!empty($user) && isset($input['newpass'])) { //find the user by their ID $user = User::find($user['_id']); //Set the newpassword, this triggers the hash function in ->save() $user->newpass = $input['newpass']; //Save the data if ($user->save(null, array('validate' => false))) { //Tell the user their password was updated sucsessfully } //Else there was an error, so send them away /* If the compare is changed to a validator * returning the user object will show the error in the view.*/ return compact('user'); } } } public function settings() { //Get the user using their login information (from auth) $user = Auth::check('default'); $user = User::find($user['id']); //If the request isn't empty if(!empty($this->request->data)) { //Foreach key/value pair in the request data foreach($this->request->data as $key => $value) { //TODO: Make sure to lock the schema to prevent wierd values $user->$key = $value; } //Save the user. $user->save(null, array('validate' => false)); } return compact('user'); } public function requestFriend($username = null) { if ($username == null) { $username = $this->request->query['username']; } //If the user isn't blocking this user, //And the user doesn't have private set //Send them a DM with a confirm key $key = confirmKey::create(); $thisUser = auth::check('default'); $url = \lithium\net\http\Router::match(array('controller' => 'users', 'action' => 'confirmFriend', 'args'=>array($thisUser['username'], $key->key)), null, array('absolute' => 'false')); $post = Post::create(array('body' => $thisUser['username'] . " want's to be your friend. Click $url to confirm")); $post->directMessage($thisUser); return $this->redirect('users::feed'); } /* Potential hack here, in theory, a user could sign up a new account * then send a direct message manually using the confirm key from the email. */ public function confirmFriend($username, $key) { /* Normally we could try and find the cKey, then if it doesn't exist * Do something about it, * However, ConfirmKey::validates basically counts the number of keys that * match $key, this is probably better than find since ->validates() may be a bit * more efficent */ $cKey = confirmKey::create(compact('key')); if ($cKey->validates()) { $thisUser = Auth::check('default'); $thisUser = User::find('first', array('conditions' => array('username' => $thisUser['username']))); $requestingUser = User::find('first', array('conditions' => compact('username'))); $requestingUser->addFriend($thisUser->username); $thisUser->addFriend($requetingUser->username); //Some action here if true :TODO: } //Some action here if false } public function step2() { //Check that step1 is completed sucsessfully, //Then take them to their profile in edit mode } } ?>