1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
|
<?php
namespace app\controllers;
use lithium\storage\Session;
use app\models\User;
use app\models\confirmKey;
use app\models\ProfilePic;
use app\models\Post;
use lithium\security\Auth;
use lithium\util\String;
use \MongoDate;
use li3_flash_message\extensions\storage\FlashMessage;
use app\libraries\openID\LightOpenID;
class UsersController extends \lithium\action\Controller {
public $secret = "marshmellows"; //I don't know why either?
//Make login a public action.
public $publicActions = array('login', 'logout', 'signup', 'confirm');
/* User profile implementation */
/* So, like twitter if you friend someone but they don't friend you,
* You can see their posts, but they don't see yours. Furthermore, posts that start with a @username
* shouldn't be shown to the user either.
*
* Now say for instance the the user isn't logged in but visits the profile of another user. It should show the users posts
* that aren't set to private. this should be as easy as Posts::find('all', array('conditions' => 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 i
* 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::create($user, array('exists' => true));
$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;
//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.
$this->render(array('layout' => 'untitled', 'data' => compact('user', 'feed')));
}
}
public function openid()
{
if ($this->request->data)
{
if (!empty($this->request->query))
{
var_dump($this->request->query);
}
else
{
$openid = new LightOpenID;
echo $openid->validates();
}
}
}
public function signup()
{
//If the request isn't empty
if($this->request->data)
{
//Create a user from the data
$user = User::Create($this->request->data);
//Until the save bug is fixed
$results = $user->validates();
if ($results)
{
//The user isn't active until after they confirm.
$user->confirmed = false;
$user->active = false;
$user->joinedOn = new MongoDate();
//Generate a confirmation key for the user
$key = confirmKey::Create(array('key' => confirmKey::generate($user->email), 'username' => $user->username));
//Save it to the database
$key->save();
//If everything goes ok
if ($user->save(null, array('validates' => false)))
{
//Store some session information
//Session::write('username', $user->username);
//Session::write('email', $user->email);
//For the debug version, send the key to the front page
$link = "/users/confirm";
return compact('key', 'link');
// /*
// //Send them to the confirmation page.
// $this->redirect('users/confirm');
}
}
else
{
return compact('user');
}
}
}
public function login($location = null, $args = null)
{
//Put in a check to make sure the user has confirmed their account
//The check should probably happen below after the auth check.
/*
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.
*/
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 = new MongoDate();
$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('Users::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
if ($location != null)
{
}
//Otherwise send them to the hompa
return $this->redirect('Users::feed');
}
else
{
FlashMessage::set('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('/');
}
private 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');
if(!empty($user) && ($data['newpass'] == $data['confirm']))
{
//find the user by their ID
$user = User::find($user['_id']);
//Set the newpassword, this triggers the hash function in ->save()
$user->newpass = $data['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 requestFriend($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');
$link = Html::link('here', "/users/confirmFriend/$this->username/$key->key");
$post = Post::create(array('body' => "$thisUser->username want's to be your friend. Click $link to confirm"));
$post->directMessage($username);
}
/* 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 confirm($key = null)
{
//Situation one
//They have a key
if (!(empty($key)))
{
//Find the key in the database
$foundKey = confirmKey::find('first', array('conditions' => compact('key')));
//If the key exists
if($foundKey != NULL)
{
/* Note: foundKey->validates() does the same check, but it was added incase more validation is needed */
//Find that user in the database
$foundUser = User::find('first', array('conditions' => array("username" => $foundKey->username)));
$valid = ($foundUser != NULL);
//Set the users account active and confirmed.
$foundUser->confirmed = true;
$foundUser->active = true;
//If the user is saved sucsessfully,
if($foundUser->save(null, array('validate' => false)))
{
/* If the save is sucsessful we are done */
//Delete their key,
$foundKey->delete();
//Send them to the homepage (probably login though)
$this->redirect("/");
}
else
{
FlashMessage::set("There was an error.");
}
}
else
{
//Otherwise
FlashMessage::set("There was an error finding the key.");
return;
}
}
}
public function step2()
{
//Check that step1 is completed sucsessfully,
//Then take them to their profile in edit mode
}
}
?>
|