<file_sep>$(document).ready(function() {
    
    var changePassword = $('#change_password'),
        activate = $('#activate_account'),
        changeDialog = $('#change_dialog'),
        activateDialog = $('#activate_dialog');
    
    
    
    activateDialog.dialog({
        autoOpen : false,
        buttons: [
                    {
                        text: "Accept",
                        click: function() {
                            activateAccount(this);
                        }
                    },
                    {
                        text: "Cancel",
                        click: function() {
                            $( this ).dialog( "close" );
                    }
                }
            ],
        height: 500,
        width: 600,
        modal: true,
        position: "center",
        resizable: false
    });
    
    if(activate.length > 0){
        activate.on('click', function(){
            activateDialog.dialog("open");
        });
    }
    
    changeDialog.dialog({
        autoOpen : false,
        buttons: [
                    {
                        text: "Submit",
                        click: function() {
                            submitChangePassword(this);
                        }
                    },
                    {
                        text: "Cancel",
                        click: function() {
                            $( this ).dialog( "close" );
                    }
                }
            ],
        height: 500,
        width: 600,
        modal: true,
        position: "center",
        resizable: false
    });
    
    changePassword.on('click', function(){
        changeDialog.dialog("open");
    });
    
    function submitChangePassword(dialog){
        var old = $(dialog).find("#old_password"),
            newP = $(dialog).find("#new_password"),
            confirm = $(dialog).find("#confirm_new_password");

        if(newP.val() !== confirm.val()){
            alert('passwords do not match!');
            return;
        }else if(newP.val().length < 6){
            alert('passwords must be a minimum of 6 characters');
            return;
        }
        
        $.ajax({
                dataType: 'json',
                type: 'POST',
                url: '/api/user/changePassword',
                data: JSON.stringify({
                    oldPassword : old.val(),
                    newPassword : <PASSWORD>()
                }),
                success:function(data){
                    if(data.message == "success"){
                        alert('Password successfully changed!');
                    }else if(data.message == "incorrect"){
                        alert('Your old password was wrong');
                    }else{
                        alert('Something went wrong');
                    }
                    $(dialog).dialog('close');
                },
                error:function(){
                
                }
        });
    }
    
    function activateAccount(dialog){
        $.ajax({
                dataType: 'json',
                type: 'POST',
                url: '/api/user/activate',
                success:function(data){
                    $('#activate_container').html('Your Account is Active');
                    $(dialog).dialog("close");
                },
                error:function(){
                
                }
        });
    }
    
});<file_sep>SMS Journal
=======================

Introduction
------------
This is a class project. I'm using ZF2, mongoDB, doctrine 2 ODM, and Nexmo to complete everything.
<file_sep><?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;
use Zend\EventManager\EventManagerInterface;
use Zend\Json\Json;
use Application\Model\UserModel;

class BaseRestfulController extends AbstractRestfulController
{

    /**
     * @var Doctrine\ODM\MongoDB\DocumentManager
     */
    protected $dm;

    /**
     * @var Application\Mapper\Manager
     */
    protected $mManager;

    public function getDocumentManager() {
        if (null === $this->dm) {
            $this->dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
        }
        return $this->dm;
    }
    
    public function getAuthenticatedUser() {
        $user = $this->zfcUserAuthentication()->getAuthService()->getIdentity();
        if(!$user){
            return $this->redirect()->toRoute('application', array('controller'=> 'index', 'action' => 'logout'));
        }
        return $user;
    }
    
    public function hasIdentity() {
        $user = $this->zfcUserAuthentication()->getAuthService()->getIdentity();
        if(!$user){
            return false;
        }
        return true;
    }

    
}

<file_sep><?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;
use Zend\EventManager\EventManagerInterface;

class ApiController extends AbstractRestfulController
{
    
    protected $collectionOptions = array('GET', 'POST');
    protected $resourceOptions = array('GET', 'PUT', 'DELETE');
    
    protected function _getOptions()
    {
        if($this->params()->fromRoute('id', false)) {
            return $this->resourceOptions;
        }
        return $this->collectionOptions;
    }
    
    public function options()
    {
        $response = $this->getResponse();
        $response->getHeaders()
                ->addHeaderLine('Allow', implode(',', $this->_getOptions()));
        
        return $response;
    }
    
    public function setEventManager(EventManagerInterface $events) {
        $this->events = $events;
        
        $events->attach('dispatch', array($this, 'checkOptions'), 10);
    }
    
    public function checkOptions($e){
        if(in_array($e->getResopnse()->getMethod(), $this->_getOptions())){
            return;
        }
        
        $response = $this->getResponse();
        $response->setStatusCode(405);
        return $response;
    }
    /**
     * Create a new resource
     *
     * @param  mixed $data
     * @return mixed
     */
    public function create($data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Delete an existing resource
     *
     * @param  mixed $id
     * @return mixed
     */
    public function delete($id)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Delete the entire resource collection
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @return mixed
     */
    public function deleteList()
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Return single resource
     *
     * @param  mixed $id
     * @return mixed
     */
    public function get($id)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Return list of resources
     *
     * @return mixed
     */
    public function getList()
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Retrieve HEAD metadata for the resource
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  null|mixed $id
     * @return mixed
     */
    public function head($id = null)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Respond to the PATCH method
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  $id
     * @param  $data
     */
    public function patch($id, $data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Replace an entire resource collection
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  mixed $data
     * @return mixed
     */
    public function replaceList($data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Modify a resource collection without completely replacing it
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.2.0); instead, raises an exception if not implemented.
     *
     * @param  mixed $data
     * @return mixed
     */
    public function patchList($data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Update an existing resource
     *
     * @param  mixed $id
     * @param  mixed $data
     * @return mixed
     */
    public function update($id, $data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }
}
<file_sep>App.views.register = Backbone.View.extend({
    el: '#register_form',
    events: {
        "click #register_submit" : "submitHandler"
    },
    submitHandler: function(){
        
    }
});<file_sep><?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
 * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return new ViewModel();
    }
    
    public function journalAction()
    {
        $user = $this->getAuthenticatedUser();
        $this->layout()->setVariable("user", $user);
        return new ViewModel();
    }
    
    public function activityAction()
    {
        $user = $this->getAuthenticatedUser();
        $this->layout()->setVariable("user", $user);
        return new ViewModel();
    }
    
    public function accountAction()
    {
        $user = $this->getAuthenticatedUser();
        $this->layout()->setVariable("user", $user);
        return new ViewModel();
    }
    
    public function registerAction()
    {
        return new ViewModel();
    }
    
    public function loginAction()
    {  
        return $this->forward()->dispatch('zfcuser', array('action' => 'login'));
    }
    
    public function logoutAction()
    {  
        $this->forward()->dispatch('zfcuser', array('action' => 'logout'));
    }
    
    public function getAuthenticatedUser() {
        $user = $this->zfcUserAuthentication()->getAuthService()->getIdentity();
        if(!$user){
            return $this->redirect()->toRoute('application', array('controller'=> 'index', 'action' => 'logout'));
        }
        return $user;
    }
}
<file_sep><?php
namespace Application\Repository;

use Doctrine\ODM\MongoDB\DocumentRepository,
    Application\Model\UserModel;

class UserRepository extends DocumentRepository
{   
    
    public function create(UserModel $user)
    {
        $user->createdOn = $user->modifiedOn = time();
        $user->status = "new";
        $user = $this->encrypt($user);
        $this->getDocumentManager()->persist($user);
        return $user;
    }
    
    public function getActiveUsers()
    {
        $query = $this->getDocumentManager()->createQueryBuilder('Application\Model\UserModel')
                        ->field('status')->equals('active');
        $cursor = $query->getQuery()->execute();
        $users = array();
        foreach($cursor as $item){
            array_push($users, $item);
        }
        return $users;
    }
    
    
    public function getByNumber($phoneNumber)
    {
        $user = $this->getDocumentManager()->createQueryBuilder('Application\Model\UserModel')
                        ->field('phone_number')->equals($phoneNumber)
                        ->getQuery()->getSingleResult();
        return $user;
    }
    
    public function update(UserModel $user){
        $user->modifiedOn = time();
        return $user;
    }
    
    public function checkPasswordCustom($user, $old)
    {
        $bcrypt = new \Zend\Crypt\Password\Bcrypt();
        $bcrypt->setCost(14);        
        $cryp = $bcrypt->create("password");
        die();
        $oldUser = new UserModel();
        $oldUser->password = $old;
        $oldUser = $this->encrypt($oldUser);
        if($user->password == $oldUser->password){
            return true;
        }
        
        return false;
    }
    
    public function encrypt(UserModel $user)
    {
        $bcrypt = new \Zend\Crypt\Password\Bcrypt();
        $bcrypt->setCost(14);        
        $user->password = $bcrypt->create($user->password);
        return $user;
    }
    
}
<file_sep><?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;
use Zend\EventManager\EventManagerInterface;
use Zend\Json\Json;
use Application\Controller\BaseRestfulContoller;
use Application\Model\JournalModel;

class JournalController extends BaseRestfulController
{
    
    public function createAction()
    {
        $user = $this->getAuthenticatedUser();
                
        $rawdata = json_decode($this->getRequest()->getContent(), true);
        $entry = new JournalModel();
        
        $entry->type = $rawdata['type'];
        $entry->entry = $rawdata['entry'];
        $entry->fromSMS = $rawdata['fromSMS'];
        $entry->fromSystem = $rawdata['fromSystem'];
        $entry->timestamp = strtotime($rawdata['date'] ." ". $rawdata['time']);
        $entry->user = $user;
        
        $journalRepo = $this->getDocumentManager()->getRepository('Application\Model\JournalModel');
        $newEntry = $journalRepo->create($entry);
        $this->getDocumentManager()->flush();

        $this->response->setStatusCode(201);        
        return new JsonModel(array('message'=>'msg', 'id' => $newEntry->id));
    }
    
    /**
     * Return list of resources
     *
     * @return mixed
     */
    public function getListAction()
    {
        $user = $this->getAuthenticatedUser();
 
        $journalRepo = $this->getDocumentManager()->getRepository('Application\Model\JournalModel');
        $journalEntries = $journalRepo->getByUser($user);
        
        $journalArray = array();
        foreach($journalEntries as $entry){
            $time = explode(" ", $entry->timestamp->format('Y-m-d H:i:s'));
            $ar = array(
                "id" => $entry->id,
                "type" => $entry->type,
                "entry" => $entry->entry,
                "date" => $time[0],
                "time" => $time[1]
            );
            $journalArray[] = $ar;
        }
        
        $this->response->setStatusCode(200);        
        return new JsonModel($journalArray);
    }

    /**
     * Delete an existing resource
     *
     * @param  mixed $id
     * @return mixed
     */
    public function delete($id)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Delete the entire resource collection
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @return mixed
     */
    public function deleteList()
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Return single resource
     *
     * @param  mixed $id
     * @return mixed
     */
    public function get($id)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Retrieve HEAD metadata for the resource
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  null|mixed $id
     * @return mixed
     */
    public function head($id = null)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Respond to the PATCH method
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  $id
     * @param  $data
     */
    public function patch($id, $data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Replace an entire resource collection
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  mixed $data
     * @return mixed
     */
    public function replaceList($data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Modify a resource collection without completely replacing it
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.2.0); instead, raises an exception if not implemented.
     *
     * @param  mixed $data
     * @return mixed
     */
    public function patchList($data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Update an existing resource
     *
     * @param  mixed $id
     * @param  mixed $data
     * @return mixed
     */
    public function update($id, $data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }
}
<file_sep><?php

namespace Application\Model;

use \Doctrine\ODM\MongoDB\Mapping\Annotations as ODM,
    \Zend\InputFilter\Input,
    \Zend\InputFilter\InputFilter,
    \Zend\Validator,
    \Zend\Filter,
    Application\Model\BaseModel;
/**
 * @ODM\Document(collection="users", repositoryClass="Application\Repository\UserRepository")
 * 
 */

class UserModel extends BaseModel implements \ZfcUser\Entity\UserInterface{

    /**
    * @ODM\Id
    */
    protected $id;
    
    /**
    * @ODM\String
    */
    protected $email;
	
    /**
    * @ODM\String
    */
    protected $password;

    /**
    * @ODM\String
    */
    protected $name;
    
    /**
    * @ODM\String
    */
    protected $phone_number;
    
    /**
     * @ODM\String
     */
    protected $status;
    
    /**
    * @ODM\Date
    */
    protected $createdOn;
    
    /**
    * @ODM\Date
    */
    protected $modifiedOn;

    
    public function getProperties(){
        return array("id", "email", "password", "name", "createdOn", "modifiedOn", "status");
    }
    
    /**
     * Define the filters used to validate the user entity
     * @return \Zend\InputFilter\InputFilter 
	 */
    protected function getFilters(){
        $inputFilter = new InputFilter();
        
        $input = new Input('email');
        $input->getValidatorChain()
            ->addValidator(new Validator\EmailAddress());
        $inputFilter->add($input);
        
        $input = new Input('password');
        $input->getValidatorChain()
            ->addValidator(new Validator\StringLength(1));
        $inputFilter->add($input);
                
        return $inputFilter;
    }

    public function getDisplayName() {
        return $this->name;
    }

    public function getEmail() {
        return $this->email;
    }

    public function getId() {
        return $this->id;
    }

    public function getPassword() {
        return $this->password;
    }

    public function getState() {
        return $this->status;
    }

    public function getUsername() {
        return $this->name;
    }

    public function setDisplayName($displayName) {
        $this->name = $displayName;
        return $this;
    }

    public function setEmail($email) {
        $this->email = $email;
        return $this;
    }

    public function setId($id) {
        $this->id = $id;
        return $this;        
    }

    public function setPassword($password) {
        $this->password = $password;
        return $this;
    }

    public function setState($state) {
        return $this;
    }

    public function setUsername($username) {
        $this->name = $username;
        return $this;
    }

}
<file_sep><?php
namespace Application\Repository;

use Doctrine\ODM\MongoDB\DocumentRepository,
    Application\Model\JournalModel,
    Application\Model\UserModel;

class JournalRepository extends DocumentRepository
{   
    
    public function create(JournalModel $entry)
    {
        $entry->createdOn = $entry->modifiedOn = time();
        $this->getDocumentManager()->persist($entry);
        return $entry;
    }
    
    public function getByUser(UserModel $user)
    {
        $query = $this->getDocumentManager()->createQueryBuilder('Application\Model\JournalModel')
                        ->field('user')->references($user)
                        ->field('fromSystem')->equals(false);
        $cursor = $query->getQuery()->execute();
        $entries = array();
        foreach($cursor as $item){
            array_push($entries, $item);
        }
        return $entries;
    }
    
}
<file_sep>$(document).ready(function() {
    
    var registerForm = $('#register_form'),
        submitBtn = $('#register_submit');
    
    submitBtn.on('click', function(event){
        submitHandler();
    });
    
    function submitHandler(){
        var user = registerForm.serializeObject(), 
            error = "";
        user.phone_number = user.phone_number.replace(/[^0-9]/g, '');
        
        if(!user.email.valueOf(user.confirm_email)){
            error += "Emails do not Match! \n";
        }
        if(!user.password.valueOf(user.confirm_password)){
            error += "Passwords do not Match! \n";
        }
        if(user.phone_number.length != 11){
            error += "Phone number is not 11 digits! \n";
        }
        if(user.name.length <1){
            error += "No name entered! \n";
        }
        
        if(error.length > 0){
            alert(error);
            return false;
        }
        
        $.ajax({
                dataType: 'json',
                type: 'POST',
                url: '/api/user/create',
                data: JSON.stringify(user), 
                success:function(data){
                    window.location.replace("/application/index/journal");
                },
                error:function(){
                
                }
        });
    }
    
    $.fn.serializeObject = function()
    {
        var o = {};
        var a = this.serializeArray();
        $.each(a, function() {
            if (o[this.name] !== undefined) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    };
});
<file_sep>App.models.User = Backbone.Model.extend({
    url: "/api/user"
    
});
<file_sep>$(document).ready(function() {
    
    var datePicker = $('#date_select'),
        dateImg = $('#date_img'),
        addEntry = $('#add_entry'),
        search = $('#search_journal'),
        journalHeader = $('#entries_header'),
        journal = $('#journal_entries'),
        addDialog = $('#add_dialog'),
        journalEntries;
    
    addDialog.dialog({
        autoOpen : false,
        buttons: [
                    {
                        text: "Submit",
                        click: function() {
                            submitEntry(this);
                        }
                    },
                    {
                        text: "Cancel",
                        click: function() {
                            closeAddDialog(this);
                    }
                }
            ],
        height: 500,
        width: 600,
        modal: true,
        position: "center",
        resizable: false
    });
    
    Date.prototype.yyyymmdd = function() {
        var yyyy = this.getFullYear().toString();
        var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based
        var dd  = this.getDate().toString();
        return yyyy +"-"+ (mm[1]?mm:"0"+mm[0]) +"-"+ (dd[1]?dd:"0"+dd[0]); // padding
    };

    var d = new Date();
    datePicker.attr('value',  d.yyyymmdd());
    
    datePicker.on('change', function(){
        populateJournal()
    });
    
    addEntry.on('click', function(){
        addDialog.dialog("open");
    });
    
    fetchEntries();
    
    function submitEntry(dialog){
        var type = $(dialog).find("#add_type"),
            hour = $(dialog).find("#add_time_hour"),
            minute = $(dialog).find("#add_time_minute"),
            period = $(dialog).find("#add_time_period"),
            entry = $(dialog).find("#add_entry_input");

        var journalEntry = {
            type : type.val(),
            date : datePicker.val(),
            time : hour.val() + ":" + minute.val() + " " + period.val(),
            entry : entry.val(),
            fromSMS : false,
            fromSystem: false
        };
        
        $.ajax({
                dataType: 'json',
                type: 'POST',
                url: '/api/journal/create',
                data: JSON.stringify(journalEntry), 
                success:function(data){
                    location.reload();
                },
                error:function(){
                
                }
        });
    }
    
    function closeAddDialog(dialog){
        $(dialog).dialog("close");
        $(dialog).html($("#add_dialog_template").html());
    }
    
    function fetchEntries(){
        $.ajax({
                dataType: 'json',
                type: 'GET',
                url: '/api/journal/get-list',
                success:function(data){
                    journalEntries = data;
                    populateJournal();
                },
                error:function(){
                
                }
        });
    }
    
    function populateJournal(){
        journal.html($('#journal_header_template').html());
        var currentDate = datePicker.val(),
            todaysEntries = [],
            i;
        if(journalEntries.length > 0){
            for(i in journalEntries){
                if(journalEntries[i].date.valueOf() == currentDate.valueOf()){
                    todaysEntries.push(journalEntries[i]);
                }
            }
            i = 0;

            todaysEntries = todaysEntries.sort(function(a,b){
                var bTime = b.time.split(":"),
                    aTime = a.time.split(":");

                bTime = bTime[0] + bTime[1] + bTime[2];
                aTime = aTime[0] + aTime[1] + aTime[2];

                return aTime - bTime;
            });

            for(i in todaysEntries){
                var html = $($(getTemplateByType(todaysEntries[i].type)).html());
                html.find('.time').html(formatTime(todaysEntries[i].time));
                html.find('.entry').html(todaysEntries[i].entry);
                journal.append("<li class='"+getOddEven(parseInt(i)+1)+"'>"+html.html()+"</li>");
            }
        }else{
            journal.append("<li class='even'>No Entries to Display</li>");
        }
        
        return;
    }
    
    function formatTime(time){
        var timeAr = time.split(":"),
            hour,
            period = "PM";
        
        if(parseInt(timeAr[0])<12){
            period = "AM";
        }
        
        if(timeAr[0].valueOf() == "00"){
            hour = "12";
        }else if(parseInt(timeAr[0]) > 12){
            hour = parseInt(timeAr[0]) - 12;
        }else{
            hour = parseInt(timeAr[0]);
        }
        
        return hour + ":" + timeAr[1] + " " + period;
    }
    
    function getOddEven(num) { 
        if((num % 2) == 1){
            return "even";
        }else{
            return "odd";
        }
    }
    
    function getTemplateByType(type){
        var id = "";
        switch (type) {
            case "activity":
                id = "run_entry_template";
                break;
            case "mood":
                id = "mood_entry_template";
                break;
            case "food":
                id = "food_entry_template";
                break;
            case "misc":
                id = "misc_entry_template";
                break;
            case "sleep":
                id = "sleep_entry_template";
                break;
            case "update":
                id = "update_entry_template";
                break;
        }
        return "#" + id;
    }
    
    $.fn.serializeObject = function()
    {
        var o = {};
        var a = this.serializeArray();
        $.each(a, function() {
            if (o[this.name] !== undefined) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    };
});<file_sep>var AppRouter = Backbone.Router.extend({
    routes: {
        "application/index/journal/:id": "journal",
        "application/index/account/:id": "account",
        "application/index/activity/:id": "activity",
        "application/index/register": "register",
        "application/index/index": "index",
        "application/index/*": "index",
        "application/*": "index",
        "": "index",
        "*actions": "defaultRoute" // Backbone will try match the route above first
    }   
});
// Initiate the router
var app_router = new AppRouter;

app_router.on('route:journal', function (id) {
    //instantiate a controller
//    alert("Journal");   
});

app_router.on('route:account', function(id) {
    //instantiate a controller
//    alert("Account");
});

app_router.on('route:activity', function (id) {
    //instantiate a controller
//    alert("Activity");   
});

app_router.on('route:register', function() {    
    new App.views.register();
});

app_router.on('route:index', function () {
    //instantiate a controller
//    alert("Index");   
});

app_router.on('route:defaultRoute', function() {
    //instantiate a controller
//    alert("Default Route");
});

// Start Backbone history a necessary step for bookmarkable URL's
Backbone.history.start({pushState: true});
<file_sep><?php

namespace DoctrineMongoODMModule\Hydrator;

use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\ODM\MongoDB\Hydrator\HydratorInterface;
use Doctrine\ODM\MongoDB\UnitOfWork;

/**
 * THIS CLASS WAS GENERATED BY THE DOCTRINE ODM. DO NOT EDIT THIS FILE.
 */
class ApplicationModelJournalModelHydrator implements HydratorInterface
{
    private $dm;
    private $unitOfWork;
    private $class;

    public function __construct(DocumentManager $dm, UnitOfWork $uow, ClassMetadata $class)
    {
        $this->dm = $dm;
        $this->unitOfWork = $uow;
        $this->class = $class;
    }

    public function hydrate($document, $data, array $hints = array())
    {
        $hydratedData = array();

        /** @Field(type="id") */
        if (isset($data['_id'])) {
            $value = $data['_id'];
            $return = $value instanceof \MongoId ? (string) $value : $value;
            $this->class->reflFields['id']->setValue($document, $return);
            $hydratedData['id'] = $return;
        }

        /** @ReferenceOne */
        if (isset($data['user'])) {
            $reference = $data['user'];
            if (isset($this->class->fieldMappings['user']['simple']) && $this->class->fieldMappings['user']['simple']) {
                $className = $this->class->fieldMappings['user']['targetDocument'];
                $mongoId = $reference;
            } else {
                $className = $this->dm->getClassNameFromDiscriminatorValue($this->class->fieldMappings['user'], $reference);
                $mongoId = $reference['$id'];
            }
            $targetMetadata = $this->dm->getClassMetadata($className);
            $id = $targetMetadata->getPHPIdentifierValue($mongoId);
            $return = $this->dm->getReference($className, $id);
            $this->class->reflFields['user']->setValue($document, $return);
            $hydratedData['user'] = $return;
        }

        /** @Field(type="string") */
        if (isset($data['type'])) {
            $value = $data['type'];
            $return = (string) $value;
            $this->class->reflFields['type']->setValue($document, $return);
            $hydratedData['type'] = $return;
        }

        /** @Field(type="date") */
        if (isset($data['timestamp'])) {
            $value = $data['timestamp'];
            if ($value instanceof \MongoDate) { $return = new \DateTime(); $return->setTimestamp($value->sec); } elseif (is_numeric($value)) { $return = new \DateTime(); $return->setTimestamp($value); } else { $return = new \DateTime($value); }
            $this->class->reflFields['timestamp']->setValue($document, clone $return);
            $hydratedData['timestamp'] = $return;
        }

        /** @Field(type="string") */
        if (isset($data['entry'])) {
            $value = $data['entry'];
            $return = (string) $value;
            $this->class->reflFields['entry']->setValue($document, $return);
            $hydratedData['entry'] = $return;
        }

        /** @Field(type="boolean") */
        if (isset($data['fromSMS'])) {
            $value = $data['fromSMS'];
            $return = (bool) $value;
            $this->class->reflFields['fromSMS']->setValue($document, $return);
            $hydratedData['fromSMS'] = $return;
        }

        /** @Field(type="boolean") */
        if (isset($data['fromSystem'])) {
            $value = $data['fromSystem'];
            $return = (bool) $value;
            $this->class->reflFields['fromSystem']->setValue($document, $return);
            $hydratedData['fromSystem'] = $return;
        }

        /** @Field(type="date") */
        if (isset($data['createdOn'])) {
            $value = $data['createdOn'];
            if ($value instanceof \MongoDate) { $return = new \DateTime(); $return->setTimestamp($value->sec); } elseif (is_numeric($value)) { $return = new \DateTime(); $return->setTimestamp($value); } else { $return = new \DateTime($value); }
            $this->class->reflFields['createdOn']->setValue($document, clone $return);
            $hydratedData['createdOn'] = $return;
        }

        /** @Field(type="date") */
        if (isset($data['modifiedOn'])) {
            $value = $data['modifiedOn'];
            if ($value instanceof \MongoDate) { $return = new \DateTime(); $return->setTimestamp($value->sec); } elseif (is_numeric($value)) { $return = new \DateTime(); $return->setTimestamp($value); } else { $return = new \DateTime($value); }
            $this->class->reflFields['modifiedOn']->setValue($document, clone $return);
            $hydratedData['modifiedOn'] = $return;
        }

        /** @Field(type="string") */
        if (isset($data['msisdn'])) {
            $value = $data['msisdn'];
            $return = (string) $value;
            $this->class->reflFields['msisdn']->setValue($document, $return);
            $hydratedData['msisdn'] = $return;
        }
        return $hydratedData;
    }
}<file_sep><?php

namespace Application\Controller;

use Zend\View\Model\JsonModel;
use Zend\Json\Json;
use Application\Controller\BaseRestfulController;
use Application\Model\JournalModel;
use Zend\Http\Response;
use Zend\Log\Logger;
use Zend\Log\Writer\Stream;
use Nexmo\NexmoAccount;
use Nexmo\NexmoMessage;
use Nexmo\NexmoReceipt;

class MessageController extends BaseRestfulController
{
    private $wakeupMsg = "Hello, our system has detected you recently woke up. How'd you sleep?";
    

    public function receiveMessageAction()
    {
        $request = $this->getRequest();
        $rawdata = $this->getRequest()->getQuery();
        $entry = new JournalModel();
        
        $logger = new Logger;
        $writer = new Stream('error.log');

        $logger->addWriter($writer);
        $logger->log(Logger::INFO, 'request uri : '.$request->getUri());
        $logger->log(Logger::INFO, 'request method : '.$request->getMethod());
        $logger->log(Logger::INFO, 'request query: '.$request->getQuery()->toString());
        
        if($rawdata['msisdn']){
            $userRepo = $this->getDocumentManager()->getRepository('Application\Model\UserModel');

            $entry->type = "misc";
            $entry->entry = $rawdata['text'];
            $entry->fromSMS = true;
            $entry->fromSystem = false;
            $entry->timestamp = strtotime($rawdata['message-timestamp']);
            $entry->user = $userRepo->getByNumber($rawdata['msisdn']);

            $journalRepo = $this->getDocumentManager()->getRepository('Application\Model\JournalModel');
            $newEntry = $journalRepo->create($entry);
            $this->getDocumentManager()->flush();
        }
        
        $response = new Response();
        $response->setStatusCode(Response::STATUS_CODE_200);
        
        $this->response = $response;
        return $this->response;
    }
    
    public function sendMessageAction()
    {
        $request = $this->getRequest();
        $rawdata = $this->getRequest()->getQuery();
        $entry = new JournalModel();
        
        $logger = new Logger;
        $writer = new Stream('error.log');

        $logger->addWriter($writer);
        $logger->log(Logger::INFO, 'request uri : '.$request->getUri());
        $logger->log(Logger::INFO, 'request method : '.$request->getMethod());
        $logger->log(Logger::INFO, 'request query: '.$request->getQuery()->toString());
        
        if($rawdata['to_number']){
            $sms = new NexmoMessage('c034c6ef', '4cde3e0f');
            $sms->sendText( $rawdata['to_number'], '17142940264', $this->wakeupMsg );
            $userRepo = $this->getDocumentManager()->getRepository('Application\Model\UserModel');
            
            $entry->type = "misc";
            $entry->entry = $this->wakeupMsg;
            $entry->fromSMS = false;
            $entry->fromSystem = true;
            $entry->timestamp = time();
            $entry->user = $userRepo->getByNumber($rawdata['to_number']);

            $journalRepo = $this->getDocumentManager()->getRepository('Application\Model\JournalModel');
            $newEntry = $journalRepo->create($entry);
            $this->getDocumentManager()->flush();
        }
        
        $response = new Response();
        $response->setStatusCode(Response::STATUS_CODE_200);
        
        $this->response = $response;
        return $this->response;
    }
    
}
<file_sep><?php
namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Nexmo\NexmoAccount;
use Nexmo\NexmoMessage;
use Nexmo\NexmoReceipt;
use Application\Model\UserModel;
use Application\Model\JournalModel;

class CronController extends AbstractActionController
{
     /**
     * @var Doctrine\ODM\MongoDB\DocumentManager
     */
    protected $dm;

    /**
     * @var Application\Mapper\Manager
     */
    protected $mManager;

    public function getDocumentManager() {
        if (null === $this->dm) {
            $this->dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
        }
        return $this->dm;
    }
    
    protected $sleepMsg = "Hey, how'd you sleep?";
    protected $foodMsg = "Have you eaten anything today?";
    protected $moodMsg = "How has your day been?";
    protected $miscMsg = "Is there anything you'd like to add to your journal?";
    
    public function sendMessagesAction()
    {
        $request = $this->getRequest();
                
        if(null !== $request->getParam('sleep')){
            return $this->sendMessageBatch($this->sleepMsg);
        }else if(null !== ($request->getParam('food'))){
            return $this->sendMessageBatch($this->foodMsg);
        }else if(null !== ($request->getParam('mood'))){
            return $this->sendMessageBatch($this->moodMsg);
        }else if(null !== ($request->getParam('misc'))){
            return $this->sendMessageBatch($this->miscMsg);
        }
        
        return "sendMessages was called";
    }
    
    public function sendMessageBatch($message){
        $userRepo = $this->getDocumentManager()->getRepository('Application\Model\UserModel');
        $activeUsers = $userRepo->getActiveUsers();
        foreach($activeUsers as $user){
            $sms = new NexmoMessage('c034c6ef', '4cde3e0f');
            $sms->sendText( $user->phone_number, '17142940264', $message );
            $userRepo = $this->getDocumentManager()->getRepository('Application\Model\UserModel');
            
            $entry = new JournalModel();
            $entry->type = "misc";
            $entry->entry = $message;
            $entry->fromSMS = false;
            $entry->fromSystem = true;
            $entry->timestamp = time();
            $entry->user = $user;

            $journalRepo = $this->getDocumentManager()->getRepository('Application\Model\JournalModel');
            $newEntry = $journalRepo->create($entry);
        }
        $this->getDocumentManager()->flush();
    }
    
}<file_sep>$(function(){
    
    /**
     * Set up our entry model
     */
    var Entry = Backbone.Model.extend({
        defaults: function(){
            return {
                type: "misc",
                entry: "default journal entry",
                date: new Date()
            }
        }
    });
    
    /**
     * Set up our entries collection
     */
    var EntryList = Backbone.Collection.extend({
        model: Entry,
        localStorage: new Backbone.LocalStorage("entries-backbone"),
        comparator: 'date'
    });
    
    /**
     * Initialize our entries collection
     */
    var Entries = new EntryList;
    
    /**
     * Set up our entry view
     */
    var EntryView = Backbone.View.extend({
        tagName:  "li",
        template: _.template($('#entry-template').html()),
        events: {
            "click .edit"   : "edit",
            "click .delete"  : "delete"
        },
        initialize: function() {
            this.listenTo(this.model, 'change', this.render);
            this.listenTo(this.model, 'destroy', this.remove);
        },
        render: function() {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        },
        edit: function() {
            //open "editing mode"
        },
        close: function() {
            //close "editing mode"
        },
        clear: function() {
           this.model.destroy();
        }
    });
    
    /**
     * Set up our top level UI element
     */
    var AppView = Backbone.View.extend({
        el: $("#journalapp"),
        events: {
            "click #new-entry":  "createNewEntry"
        },
        initialize: function() {

            this.listenTo(Entries, 'add', this.addOne);
            this.listenTo(Entries, 'reset', this.addAll);
            this.listenTo(Entries, 'all', this.render);

            this.main = $('#main');

            Entries.fetch();
        },
    });
    
});

function getCurrentDate(){
    var today = new Date();
    var dd = today.getDate();
    var mm = today.getMonth()+1; //January is 0!
    var yyyy = today.getFullYear();

    if(dd<10) {
        dd='0'+dd
    } 

    if(mm<10) {
        mm='0'+mm
    } 

    today = mm+'/'+dd+'/'+yyyy;
    return today;
}

<file_sep><?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;
use Zend\EventManager\EventManagerInterface;
use Zend\Json\Json;
use Application\Controller\BaseRestfulContoller;
use Application\Model\UserModel;

class UserController extends BaseRestfulController
{
    public function createAction()
    {
        $rawdata = json_decode($this->getRequest()->getContent(), true);
        $user = new UserModel();
        $user->email = $rawdata['email'];
        $user->password = $rawdata['password'];
        $user->phone_number = $rawdata['phone_number'];
        $user->name = $rawdata['name'];
        
        $userRepo = $this->getDocumentManager()->getRepository('Application\Model\UserModel');
        $newUser = $userRepo->create($user);
        $this->getDocumentManager()->flush();

        $this->response->setStatusCode(201);        
        return new JsonModel(array('message'=>'msg', 'id' => $newUser->id));
    }
    
    public function activateAction()
    {
        $user = $this->getAuthenticatedUser();
        $rawdata = json_decode($this->getRequest()->getContent(), true);
        $user->status = "active";
        
        $userRepo = $this->getDocumentManager()->getRepository('Application\Model\UserModel');
        $newUser = $userRepo->update($user);
        $this->getDocumentManager()->flush();

        return new JsonModel(array('message'=>'success'));
    }
    
    public function changePasswordAction()
    {
        $user = $this->getAuthenticatedUser();
        $rawdata = json_decode($this->getRequest()->getContent(), true);
        $userRepo = $this->getDocumentManager()->getRepository('Application\Model\UserModel');
        $user->password = $rawdata['<PASSWORD>'];
        $user = $userRepo->encrypt($user);
        $userRepo->update($user);
        $this->getDocumentManager()->flush();
        $message = "success";


        return new JsonModel(array('message'=>$message));
    }

    /**
     * Delete an existing resource
     *
     * @param  mixed $id
     * @return mixed
     */
    public function delete($id)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Delete the entire resource collection
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @return mixed
     */
    public function deleteList()
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Return single resource
     *
     * @param  mixed $id
     * @return mixed
     */
    public function get($id)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Return list of resources
     *
     * @return mixed
     */
    public function getList()
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Retrieve HEAD metadata for the resource
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  null|mixed $id
     * @return mixed
     */
    public function head($id = null)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Respond to the PATCH method
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  $id
     * @param  $data
     */
    public function patch($id, $data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Replace an entire resource collection
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.1.0); instead, raises an exception if not implemented.
     *
     * @param  mixed $data
     * @return mixed
     */
    public function replaceList($data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Modify a resource collection without completely replacing it
     *
     * Not marked as abstract, as that would introduce a BC break
     * (introduced in 2.2.0); instead, raises an exception if not implemented.
     *
     * @param  mixed $data
     * @return mixed
     */
    public function patchList($data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }

    /**
     * Update an existing resource
     *
     * @param  mixed $id
     * @param  mixed $data
     * @return mixed
     */
    public function update($id, $data)
    {
        $this->response->setStatusCode(405);

        return array(
            'content' => 'Method Not Allowed'
        );
    }
}
