UsersController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. <?php
  2. namespace app\controllers;
  3. use lithium\storage\Session;
  4. use app\models\User;
  5. use app\models\confirmKey;
  6. use app\models\ProfilePic;
  7. use app\models\Post;
  8. use lithium\security\Auth;
  9. use lithium\util\String;
  10. use li3_flash_message\extensions\storage\FlashMessage;
  11. use lithium\template\helper\Html;
  12. class UsersController extends \lithium\action\Controller {
  13. //Make login a public action.
  14. public $publicActions = array('login', 'logout', 'signup', 'confirm');
  15. /* User profile implementation */
  16. /* So, like twitter if you friend someone but they don't friend you,
  17. * You can see their posts, but they don't see yours. Furthermore, posts that start with a @username
  18. * shouldn't be shown to the user either.
  19. *
  20. * Now say for instance the the user isn't logged in but visits the profile of another user. It should show the users posts
  21. * that aren't set to private. this should be as easy as Posts::find('all', array('conditions' => array('level' != private)))
  22. * However, we need to differentiate posts that are Hidden (posts that begin with a @username), Friends only (set by user) or
  23. * Public (by default all posts.) there should be a method that filters the new post method, that takes a post, determines
  24. * what access level it should be then passes that back to the calling method (in save?)
  25. *
  26. * Of course, for logged in users, we need to do a multiselect I guess, something like find posts where access level is hidden
  27. * friends only, and public, ordered by date (descending) limit 20 or so (use pagination plugin)
  28. *
  29. * Finally, there should be an an option to make all posts private, this can be done by the postlevel() method, it can check if
  30. * the user has the private option set, then if true return private for all posts :)
  31. */
  32. public function index($username = null)
  33. {
  34. //If no username was entered,
  35. if ($username == null)
  36. {
  37. //Show a user list?
  38. // TODO: Pagination
  39. //Show a list of all users
  40. $users = User::all();
  41. return compact('users');
  42. //maybe we can use the endpoint hook and show a "network activity feed"
  43. //For example show all public posts as they get posted using ajax ?
  44. //Maybe we should have a route for this? /activity maybe?
  45. }
  46. //Otherwise get that user
  47. $user = User::find('first', array('conditions' => compact('username')));
  48. //find all posts, sort by date, order descending, limit to 20
  49. $feed;
  50. //Dont know if php will keep counts return on the stack so I'm storing it to avoid calling it 3 times.
  51. $tmpCount = count($user->feed);
  52. //If the user has 20 or more posts then query 20, otherwise query the number of posts the user has
  53. $count = ($tmpCount >= 20) ? 20 : $tmpCount;
  54. //If the user is logged in
  55. $user = Auth::check('default');
  56. if ($user)
  57. {
  58. if ($user->username == $username)
  59. {
  60. $feed = $user->getPosts(array('level' => null));
  61. return compact($feed, $user);
  62. }
  63. //if the user is logged in and the users are friends
  64. if (User::areFriend(Auth::check('default'), $user))
  65. {
  66. $feed = $user->getPosts(array('level' => null));
  67. return compact($feed, $user);
  68. }
  69. } //If they aren't friend, or if the user isn't logged in it defaults to the public version (filter private posts)
  70. //If the user isn't logged in, then we should show a signup partial like twitter
  71. else
  72. {
  73. //find all non-private posts, limit 20, order descending (decending was taken care of with array_unshift btw)
  74. $feed = $user->getPost(array('level' => array('$ne' => "private")));
  75. return compact($feed, $user);
  76. }
  77. }
  78. /**
  79. * How this method should work:
  80. * Since this network is default open like twitter, there is three types of relationships:
  81. * 1) Mutually Oblivious: Neither user knows each other.
  82. * 2) You Follow: You follow a user and sees their non-private posts
  83. * 3) Friends: being friends allows you to see each others privates posts
  84. * (@see app\models\post) for an example of how this works
  85. *
  86. * Now, for now there are two types of requests: Friend requests which causes both users to automatically follow eachother
  87. * And follows. Follows are unidirectional and thus don't require the followees permission
  88. */
  89. public function follow($username = null)
  90. {
  91. $status;
  92. $message;
  93. if($this->request->data)
  94. {
  95. $user = Auth::check('default');
  96. if ($user)
  97. {
  98. $user = User::find('first', array('conditions' => array('username' => $user['username'])));
  99. if ($user->follow($username))
  100. {
  101. $status = true;
  102. return array('succeeded' => true, 'message' => 'You are now following $username');
  103. }
  104. }
  105. }
  106. }
  107. /**
  108. * Calls the user to addFriend method, then returns the status.
  109. * @param username The name of the user to add as a friend
  110. */
  111. public function addfriend($username = null)
  112. {
  113. }
  114. public function reconfirm()
  115. {
  116. //Search the database for email address
  117. if (ConfirmKey::count(array('conditions' => array('email' => $this->request->data['email']))) != 0)
  118. {
  119. //Resend the confirmation email
  120. }
  121. else
  122. {
  123. //Show them a message
  124. }
  125. //Send a new key
  126. }
  127. public function profile($username)
  128. {
  129. //If no username is passed in.
  130. if (empty($username))
  131. {
  132. $this->redirect('/');
  133. }
  134. //Otherwise
  135. else
  136. {
  137. //Find that user, and go to their profile page.
  138. $user = User::find('first', array('conditions' => compact('username')));
  139. //$photo = (empty($user->profilepic) ? ProfilePic::create() : $user->profilepic);
  140. return compact('user', 'photo');
  141. //Render the profile layout
  142. }
  143. }
  144. public function post()
  145. {
  146. if ($this->request->data)
  147. {
  148. $user = Auth::check('default');
  149. if ($user) {
  150. $user = User::find($user['id']);
  151. $user->post($this->request->data);
  152. }
  153. /* :TODO: Need to return a status here */
  154. $this->redirect('Users::feed');
  155. }
  156. }
  157. public function feed()
  158. {
  159. //Get the currently logged in user
  160. $user = Auth::check('default');
  161. $user = User::find($user['id']);
  162. return compact('user', 'feed');
  163. }
  164. /*
  165. If the user is valid, but not confirmed,
  166. tell the user they haven't confirmed,
  167. offer to resend the confirmation email or changed their email address.
  168. */
  169. public function login($location = null, $args = null)
  170. {
  171. if (!empty($this->request->data)) {
  172. $user = Auth::check('default', $this->request);
  173. if ($user)
  174. {
  175. $user = User::find('first', array('conditions' => array('username' => $user['username'])));
  176. $user->lastLogin = date('Y-m-d H:i:s', time());
  177. $user->save(null, array('validate' => false));
  178. //If the user hasn't confirmed their account
  179. if(!$user->confirmed)
  180. {
  181. //Redirect them to the confirmation page.
  182. return $this->redirect('Signup::confirm');
  183. }
  184. //If the user's account is not active they are probably banned
  185. if (!$user->active)
  186. {
  187. return $this->redirect('/pages/banned');
  188. }
  189. //If the user was trying to go somewhere, redirect them there
  190. $loc = Session::read('url');
  191. if (isset($loc))
  192. {
  193. Session::delete('url');
  194. return $this->redirect(array('controller' => $loc['controller'],
  195. 'action' => $loc['action'],
  196. 'args' => $loc['args']
  197. ));
  198. }
  199. //Otherwise send them to the hompa
  200. return $this->redirect('Users::feed');
  201. }
  202. else
  203. {
  204. FlashMessage::write('Username or Password Incorrect.');
  205. }
  206. }
  207. }
  208. //Logout
  209. public function logout()
  210. {
  211. //If the user logs out
  212. //Clear their auth cookie
  213. Auth::Clear('default');
  214. //Redirect them to the homepage.
  215. return $this->redirect('/');
  216. }
  217. public function changePassword()
  218. {
  219. //Get the user to verify their current password
  220. $input = $this->request->data;
  221. //If there is inputfrom the form
  222. if ($input)
  223. {
  224. //Get the user from auth
  225. $user = Auth::check('default');
  226. //Ensure that the passwords are the same.
  227. if ($input['newpass'] != $input['confirm'])
  228. {
  229. //return error
  230. return $this->redirect('/');
  231. }
  232. else if(!empty($user) && isset($input['newpass']))
  233. {
  234. //find the user by their ID
  235. $user = User::find($user['_id']);
  236. //Set the newpassword, this triggers the hash function in ->save()
  237. $user->newpass = $input['newpass'];
  238. //Save the data
  239. if ($user->save(null, array('validate' => false))) {
  240. //Tell the user their password was updated sucsessfully
  241. }
  242. //Else there was an error, so send them away
  243. /* If the compare is changed to a validator
  244. * returning the user object will show the error in the view.*/
  245. return compact('user');
  246. }
  247. }
  248. }
  249. public function settings()
  250. {
  251. //Get the user using their login information (from auth)
  252. $user = Auth::check('default');
  253. $user = User::find($user['id']);
  254. //If the request isn't empty
  255. if(!empty($this->request->data)) {
  256. //Foreach key/value pair in the request data
  257. foreach($this->request->data as $key => $value)
  258. {
  259. //TODO: Make sure to lock the schema to prevent wierd values
  260. $user->$key = $value;
  261. }
  262. //Save the user.
  263. $user->save(null, array('validate' => false));
  264. }
  265. return compact('user');
  266. }
  267. public function requestFriend($username = null) {
  268. if ($username == null)
  269. {
  270. $username = $this->request->query['username'];
  271. }
  272. //If the user isn't blocking this user,
  273. //And the user doesn't have private set
  274. //Send them a DM with a confirm key
  275. $key = confirmKey::create();
  276. $thisUser = auth::check('default');
  277. $url = \lithium\net\http\Router::match(array('controller' => 'users',
  278. 'action' => 'confirmFriend',
  279. 'args'=>array($thisUser['username'], $key->key)), null, array('absolute' => 'false'));
  280. $post = Post::create(array('body' => $thisUser['username'] . " want's to be your friend. Click $url to confirm"));
  281. $post->directMessage($thisUser);
  282. return $this->redirect('users::feed');
  283. }
  284. /* Potential hack here, in theory, a user could sign up a new account
  285. * then send a direct message manually using the confirm key from the email.
  286. */
  287. public function confirmFriend($username, $key) {
  288. /* Normally we could try and find the cKey, then if it doesn't exist
  289. * Do something about it,
  290. * However, ConfirmKey::validates basically counts the number of keys that
  291. * match $key, this is probably better than find since ->validates() may be a bit
  292. * more efficent */
  293. $cKey = confirmKey::create(compact('key'));
  294. if ($cKey->validates())
  295. {
  296. $thisUser = Auth::check('default');
  297. $thisUser = User::find('first', array('conditions' => array('username' => $thisUser['username'])));
  298. $requestingUser = User::find('first', array('conditions' => compact('username')));
  299. $requestingUser->addFriend($thisUser->username);
  300. $thisUser->addFriend($requetingUser->username);
  301. //Some action here if true :TODO:
  302. }
  303. //Some action here if false
  304. }
  305. public function step2()
  306. {
  307. //Check that step1 is completed sucsessfully,
  308. //Then take them to their profile in edit mode
  309. }
  310. }
  311. ?>