summaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/Anime.php8
-rw-r--r--models/Entry.php9
-rw-r--r--models/Photo.php62
-rw-r--r--models/Post.php137
-rw-r--r--models/Profile.php17
-rw-r--r--models/ProfilePic.php28
-rw-r--r--models/Topic.php13
-rw-r--r--models/User.php347
-rw-r--r--models/confirmKey.php46
-rw-r--r--models/contentList.php17
-rw-r--r--models/untitled.php18
11 files changed, 702 insertions, 0 deletions
diff --git a/models/Anime.php b/models/Anime.php
new file mode 100644
index 0000000..ffa40eb
--- /dev/null
+++ b/models/Anime.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace app\models;
+
+class Anime extends \lithium\data\Model {
+ protected $_meta = array('key' => '_id', 'source' => 'anime');
+
+} \ No newline at end of file
diff --git a/models/Entry.php b/models/Entry.php
new file mode 100644
index 0000000..3b27393
--- /dev/null
+++ b/models/Entry.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace app\models;
+
+Class entry extends \lithium\data\Model {
+ public static function __init() {
+ parent::__init();
+ }
+} \ No newline at end of file
diff --git a/models/Photo.php b/models/Photo.php
new file mode 100644
index 0000000..364b9fa
--- /dev/null
+++ b/models/Photo.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace app\models;
+
+class Photo extends \lithium\data\Model {
+
+ //Tells lithium to store it in mongo as a file (gridFS)
+ protected $_meta = array('source' => 'fs.files');
+ public $validates = array();
+
+
+ /**
+ * Generate a cached version under webroot
+ * @param string $id The image id as in mongodb
+ * @param array $options Possible values are
+ * width
+ * height
+ * @return mixed
+ */
+ public static function version($id, $options = array()) {
+ if (!$id)
+ return false;
+ // This is the same as Photo::first($id) when called from inside itself
+ $self = static::first($id);
+ return ($self) ? $self->generateVersion($options) : false;
+ }
+
+ /**
+ * Generate a cached version under webroot
+ * @param Document $self The document from the db
+ * @param array $options Possible values are
+ * @return mixed
+ */
+ public function generateVersion($self, $options = array()) {
+ // This is quite naive, it would fail at .jpeg for example. Be more elaborate on production code!
+ $type = substr($self->file->file['filename'], -3);
+ $path = LITHIUM_APP_PATH . "/webroot/image/{$self->_id}";
+ $originalPath = $path . "." . $type;
+
+ // Always create the original variant if it doesnt exist yet. It is needed for resize
+ if (!file_exists($originalPath))
+ file_put_contents($originalPath, $self->file->getBytes());
+
+ if (isset($options['width']) && isset($options['height'])) {
+ $width = (int) $options['width'];
+ $height = (int) $options['height'];
+
+ $path .= "_{$width}x{$height}.{$type}";
+
+ // This requires imagemagick and access to system calls.
+ // It is possible to use gd but it is a much worse alternative so please dont.
+ $convertCommand = "convert $originalPath -resize {$width}x{$height}\> $path";
+ shell_exec($convertCommand);
+ // Return data of the resized version
+ return file_get_contents($path);
+ }
+ // If no width/height were set, just return data of the original
+ return $self->file->getBytes();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/models/Post.php b/models/Post.php
new file mode 100644
index 0000000..653beb2
--- /dev/null
+++ b/models/Post.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace app\models;
+use app\models\User;
+
+class Post extends \lithium\data\Model {
+ protected $_meta = array('key' => '_id');
+
+//Overrides save so we can do some stuff before the data is commited to the database.
+
+/* Post model $_Schema:
+ * _id => MongoID
+ * user_id -> mongoID of the user that posted it
+ * datetime -> mongodate of when the post was posted
+ * body -> the text of the post
+ * level -> access level required to see the post
+ * comments[] => list of comments
+ * type -> the type of post, IE picture text, chat etc
+ */
+
+ /**
+ * Parses an array of words to find mentions and topic tags then converts them
+ * @param Entitiy $entity Not used, but otherwise lithium will pass entity into words which makes the program blowup
+ * @param Mixed $input, either a string, or a spilt array of words (ie an exploded string)
+ * @return String a string with the topics and mentions converted
+ */
+ public function parse($entity, $input)
+ {
+ $words;
+ if (is_array($input)) {
+ $words = $input;
+ }
+ else {
+ $words = explode(" ", $input);
+ }
+
+ //Count the number of words
+ $count = count($words);
+
+
+ //For each word in the array
+ for ($i = 0; $i < $count; $i++)
+ {
+ //If the word begins with a '@' convert it to a mention
+ if ($words[$i][0] == '@')
+ {
+ $words[$i] = $this->convertToMention($words[$i]);
+ }
+ //Else if the word beings with a '#' Convert to topic link
+ else if ($words[$i][0] == '#')
+ {
+ $words[$i] = $this->convertToTopic($words[$i]);
+ }
+ }
+ return implode(" ", $words);
+ }
+
+ //TODO: Some sort of security check to make sure
+ //That the user is ok with receiving message
+
+ public function directMessage($entity, $to)
+ {
+ //Get the user the message is to
+ $user = User::find('first', array('conditions' => array('username' => $to)));
+
+ //If find() returned a user,
+ if ($user)
+ {
+ //Add the post to their feed,
+ return $post->store($user);
+ }
+ //If the user wasn't found
+ return false;
+ }
+
+ /**
+ * Converts a string with a topic tag(eg: #madoka) to clickable link to the topic eg <a class="topic" href"/topic/madoka>#madoka</a>
+ * @param String $input The string with topic tag
+ * @return String the string with href
+ */
+ public function convertToTopic($input)
+ {
+ //Remove the # character from the beginning
+ $output = substr($input, 1);
+
+ //Formats the string and returns it.
+ return "<a class=\"topic\" href=\"/topics/view/$output\">$input</a>";
+ }
+
+ /**
+ * converts a mention (eg: @bob) to a clickable link to the user's profile eg <a class="topic" href"/topic/madoka>#madoka</a>
+ * @param String $input The string with topic tag
+ * @return String the string with href
+ */
+ public function convertToMention($input)
+ {
+ //Remove the @ character from the beginning
+ $output = substr($input, 1);
+
+ //Formats the string and returns it.
+ return "<a class=\"mention\" href=\"/profile/view/$output\">$input</a>";
+ }
+
+ /**
+ * Stores the post to all the user's friends feed
+ * @param Post $entity The post to be stored
+ * @param Array $users an Array of users objects to store the post to
+ * @return boolean True if sucsessful, false otherwise
+ */
+ //Store all can take a single param as well, therefore it should replace the store method once we're sure it works properly :TODO:
+ public function storeAll($entity, $users)
+ {
+ $ids;
+ foreach($users as $user)
+ {
+ $ids[] = $user->_id;
+ }
+
+ $updateData = array('$push' => array('feed' => $entity['_id']->__toString()));
+
+ $conditions = array('_id' => array('$in' => $ids));
+ $result = User::update($updateData, $conditions, array('atomic' => false));
+
+ return $result;
+ }
+
+ public function store($entity, $user)
+ {
+ $updateData = array('$push' => array('feed' => $entity['_id']->__toString()));
+ $conditions = array('_id' => $user['_id']);
+ $result = User::update($updateData, $conditions, array('atomic' => false));
+
+ return $result;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/models/Profile.php b/models/Profile.php
new file mode 100644
index 0000000..a85be6d
--- /dev/null
+++ b/models/Profile.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace app\models;
+
+class Profile extends \lithium\data\Model {
+ public static function __init()
+ {
+ Validator::add('ageism', function($birthday) {
+ return true;
+ } );
+ }
+ public $validates = array(
+ 'birthday' => array(array('date'))
+ );
+}
+
+?> \ No newline at end of file
diff --git a/models/ProfilePic.php b/models/ProfilePic.php
new file mode 100644
index 0000000..079f5b7
--- /dev/null
+++ b/models/ProfilePic.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace app\models;
+
+
+//Import image magic (lazy load)
+use imagick;
+
+
+class ProfilePic extends \lithium\data\Model {
+ //Where we are going to store the files in mongoDB
+ protected $_meta = array('source' => 'fs.files');
+
+ //Overriding save to do the thumbnailing :)
+ public function save($entity, $data, array $options = array())
+ {
+ //Create a new imagemagick object from the uploaded file
+ $im = new Imagick($data['file']);
+
+ //Create a thumbnail of the file, then store it in the "thumbnail" object
+ $data['thumbnail'] = $im->thumbnailImage(200, null);
+
+ //Pass the changes off to the original save method.
+ return parent::save($entity, $data, $options);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/models/Topic.php b/models/Topic.php
new file mode 100644
index 0000000..6f12aa2
--- /dev/null
+++ b/models/Topic.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace app\models;
+
+class Topic extends \lithium\action\Model {
+ public function __init()
+ {
+ parent::__init();
+
+ //Vadidators
+
+ }
+} \ No newline at end of file
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
diff --git a/models/confirmKey.php b/models/confirmKey.php
new file mode 100644
index 0000000..6a941ad
--- /dev/null
+++ b/models/confirmKey.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace app\models;
+
+
+use lithium\util\String;
+use lithium\util\Validator;
+
+class confirmKey extends \lithium\data\Model {
+ //Comfirmation Key "salt"
+ public $secret = "marshmellows"; //I don't know why either?
+
+ //To bypass mongo bug
+ protected $_meta = array('key' => '_id');
+ //array('isValidKey', 'message' => 'Key does not exist');
+
+ public static function __init()
+ {
+ //Make sure the class we extend inits.
+ parent::__init();
+
+ //Checks if the key is valid (in the database);
+ Validator::add('isValidKey', function($key) {
+ return confirmKey::count(array('conditions' => compact('key'))) == 1;
+ });
+ }
+
+ //For now, this will remain, but eventually it should just filter the save
+ //Method since the confirmation key doesn't really need to be returned to the controller.
+ public function generate($email)
+ {
+ //Doesn't need to be ultra secure since they just need to click the generated link
+ return String::hash($email.$this->secret, array('type' => 'crc32'));
+ }
+
+ /*
+ * Old Validates function
+ public function isValidKey($key)
+ {
+ //If they key is valid, it should be found in the database
+ //If there is 1 key that matches the input key,
+ return confirmKey::count(array('conditions' => compact('key'))) == 1;
+ }
+ */
+}
+?> \ No newline at end of file
diff --git a/models/contentList.php b/models/contentList.php
new file mode 100644
index 0000000..017e261
--- /dev/null
+++ b/models/contentList.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace app\models;
+
+class contentList extends \lithium\data\Model {
+ public function update()
+ {
+
+ }
+
+ public function add($entity, $data)
+ {
+ $updateData = array('$push' => array(''
+ $conditions = array('_id' => $user['_id']);
+ $result = User::update($updateData, $conditions, array('atomic' => false));
+ }
+} \ No newline at end of file
diff --git a/models/untitled.php b/models/untitled.php
new file mode 100644
index 0000000..46fd26c
--- /dev/null
+++ b/models/untitled.php
@@ -0,0 +1,18 @@
+<?php
+
+session_start();
+
+if ($_POST["password"] == "chaaya")
+{
+ if($_POST["username"] == "achaaya")
+ {
+ $_Session["name"] = "Andrew Chaaya";
+ $_Session["grades"] = ""
+ }
+ else
+ {
+ $_Session["name"] = "Joanne Chaaya";
+ }
+}
+
+?> \ No newline at end of file