I'm rewriting a god object with long methods into something much more viewable and pretty.
However, I think there is something missing and can be done better. I'm sending examples of one controller and two models in order to get an idea.
Controller: Account.php
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
* handle accounts transformations
*/
class Account extends CI_Controller {
function __construct()
{
parent::__construct();
$this->load->model("outputModel");
$this->load->model("userModel");
$this->load->model('validation');
$this->load->database();
}
/**
* login
*
* @post email
* @post password
* @post device_token optional
* @post device_family optional
*
* @return OutputModel $outputModel auth_token
*/
function index() {
$email = $this->input->post('email');
$password = $this->input->post('password');
if (isset($_POST['device_token']) && isset($_POST['device_family'])) {
$device_token = $this->input->post('device_token');
$device_family = $this->input->post('device_family');
$result = $this->userModel->Login($email,$password,$device_token,$device_family);
} else {
$result = $this->userModel->Login($email,$password);
}
$this->outputModel->process($result);
echo $this->outputModel;
}
/**
* get unread messages and groupchats from (last) dated up to limit
*
* @post string $auth_token
* @post int $limit amount of groupchats requested
* @post int $date_up_to unixtime optional
* @post boolean $order_by_date_desc optional
*
* @return OutputModel $outputModel echo jsoned
*/
function refresh() {
$token = $this->input->post('auth_token');
$data['user_id'] = $this->validation->checkSession($token);
$data['limit'] = $this->input->post('limit');
if (isset($_POST['date_up_to']))
$data['date_up_to'] = $this->input->post('date_up_to');
if (isset($_POST['order_by_date_desc']))
$data['order_by_date_desc'] = $this->input->post('date_up_to');
$result = $this->groupChatModel->getUnread($data);
$this->outputModel->processResult($result);
echo $this->outputModel;
}
function activate($activation_key) {
if (!$this->validation->checkSHA256($activation_key)) {
$this->load->view("activate_unsuccessful.php");
return;
} else {
//continue
}
$this->load->library('email');
$this->load->helper('url');
$this->load->database();
$this->load->helper('string');
# check account exists
$sql = "SELECT * FROM user WHERE activation_key = ?";
$query = $this->db->query($sql, array($activation_key));
if ($query->num_rows() > 0) {
# activate account
$sql = "UPDATE user SET activation_key = 0 WHERE activation_key = ?";
$this->db->query($sql, array($activation_key));
$this->load->view("activate_successful.php");
} else {
$this->load->view("activate_unsuccessful.php");
}
}
/**
* creates account
*
* @post string first_name
* @post string last_name
* @post string phone
* @post string email
* @post string password
*
* @return OutputModel $outputModel auth_token on success or error
*
*/
function create()
{
$this->load->model('userModel');
$first_name = $this->input->post('first_name');
$last_name = $this->input->post('last_name');
$phone = $this->input->post('phone');
$email = $this->input->post('email');
$password = $this->input->post('password');
$result = $this->userModel->CreateAccount($first_name, $last_name, $phone, $email, $password);
$this->outputModel->process($result);
echo $this->outputModel;
}
/**
* changes setting of an account
*
* @post string auth_token
* @post string new_first_name
* @post string new_last_name
* @post string new_phone
* @post string new_password
* @post string old_password
*
*
* @return OutputModel $outputModel auth_token on success or error
*/
function changeSettings() {
$token = $this->input->post('auth_token');
$data['user_id'] = $this->validation->checkSession($token);
$data['new_first_name'] = $this->input->post('new_first_name');
$data['new_last_name'] = $this->input->post('new_last_name');
$data['new_phone'] = $this->input->post('new_phone');
$data['new_password'] = $this->input->post('new_password');
$data['old_password'] = $this->input->post('old_password');
$result = $this->userModel->ChangeSettings($data);
$this->outputModel->process($result);
echo $this->outputModel;
}
}
Models:
1. UserModel
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class UserModel extends CI_Model {
/**
* @param $email
* @param $password
* @param null $device_token
* @param null $device_family
* @return array
*/
public function Login($email, $password, $device_token = null, $device_family = null )
{
$sql = "SELECT * FROM user WHERE (email = ?) LIMIT 1";
$query = $this->db->query($sql, array(strtolower($email)));
if (!($query->num_rows() > 0)){
$error = #some code error
return array('error' => $error);
} else {
//continue
}
$row = $query->row();
if ($row->password != encrypt($password) {
$error = #some code error
return array('error' => $error);
} else {
//continue
}
# Create a session id and store it in session table with device token and device family
$user_id = $row->id;
$token = hash(func,uniqid());
$expire_date = time() + (24*60*60); //now + 24 hours
$sql = "INSERT INTO auth_tokens (auth_token, user_id, expire_date) VALUES (?, ?, ?)";
$this->db->query($sql, array($token, $user_id, $expire_date));
# Create entry in devicetoken table
if ($device_token && $device_family) {
$this->AddDevice($user_id, $device_token, $device_family);
}
# put session id and user id into response
$response['auth_token'] = $token;
$response['id'] = $user_id;
$response['first_name'] = $row->first_name;
$response['last_name'] = $row->last_name;
return array('result' => $response);
}
/**
* @param $user_id
* @param $device_token
* @param $device_family
* @return void
*/
public function AddDevice($user_id,$device_token,$device_family) {
$sql = "SELECT * FROM devicetoken WHERE device_token = ? AND device_family = ?";
$query = $this->db->query($sql, array($device_token, $device_family ));
if (!$query->num_rows() == 0) {
$sql = "UPDATE devicetoken SET user_id = ?, device_family = ? WHERE device_token = ?";
$this->db->query($sql, array($user_id, $device_family, $device_token));
} else {
$sql = "INSERT INTO api_devicetoken(user_id,device_token,device_family) VALUES (?,?,?)";
$this->db->query($sql, array($user_id,$device_token,$device_family));
}
return;
}
/**
* @param array $data
* @return array
*/
public function ChangeSettings(array $data) {
$this->load->model('validation');
$sql = "SELECT * FROM user WHERE id = ?";
$query = $this->db->query($sql, $data['user_id']);
if ($query->num_rows() == 0) {
return array('error' => #some code error);
}
$row = $query->row();
//check password
if ($row->password!=encrypt($data['old_password'])) {
return array('error' => #some code error);
}
//(process|substitute old) first name
if (array_key_exists('new_first_name',$data)) {
if (!$this->validation->checkName($data['new_first_name'])) {
return array('error' => #some code error);
}
} else {
$data['new_first_name'] = $row->first_name;
}
//(process|substitute old) last name
if (array_key_exists('new_last_name',$data)) {
if (!$this->validation->checkName($data['new_last_name'])) {
return array('error' => #some code error);
}
} else {
$data['new_last_name'] = $row->last_name;
}
//(process|substitute old) phone
if (array_key_exists('new_phone',$data)) {
if (!$this->validation->checkName($data['new_phone'])) {
return array('error' => #some code error);
}
} else {
$data['new_phone'] = $row->phone;
}
//(process|substitute old) new password
if (array_key_exists('new_password',$data)) {
if (!$this->validation->checkPass($data['new_password'])) {
return array('error' => #some code error);
}
} else {
$data['new_password'] = $data['old_password'];
}
$data['new_password'] = encrypt($data['new_password']);
$sql = "UPDATE user SET first_name = ?, last_name = ?, password = ? WHERE id = ?";
$this->db->query($sql, array($data['new_first_name'],$data['new_last_name'],
$data['new_password'],$data['user_id']));
if (!$this->db->affected_rows()) {
return array('error' => #some code error);
}
// update phone
$sql = "UPDATE api_user_data SET value = ?, hash = ? WHERE user_id = ? AND type_id = 3";
$this->db->query($sql, array($data['new_phone'], hash($data['new_phone']), $data['user_id']));
unset($data['new_password']);
unset($data['old_password']);
return array('result' => $data);
}
/**
* @param $first_name
* @param $last_name
* @param $phone
* @param $email
* @param $password
* @return array
*/
public function CreateAccount($first_name, $last_name, $phone, $email, $password) {
$this->load->model('validation');
if (!$this->validation->checkName($first_name))
return array('error' => #some code error);
if (!$this->validation->checkName($last_name))
return array('error' => #some code error);
if (!$this->validation->checkPhone($phone))
return array('error' => #some code error);
if (!$this->validation->checkEmail($email))
return array('error' => #some code error);
if (!$this->validation->checkPass($password))
return array('error' => #some code error);
# Check if email address exists: error = #some code error if yes
# If email exists, but not verified - resend verification is to be used
$sql = "SELECT * FROM user WHERE email = ?";
$query = $this->db->query($sql, array($email));
if ($query->num_rows() > 0)
return array('error' => #some code error); //user already exists
# create activation key
$key = encrypt(uniqid());
# prepare password
$password = encrypt($password);
# store user details with activation key
$sql = "INSERT INTO user (first_name, last_name, password, user_type, activation_key) VALUES (?,?,?,?,?)";
$query = $this->db->query($sql, array($first_name, $last_name, $password, 1, $key)); //1 means type of user
if ($query) {
$user_id = $this->db->insert_id();
$sql = "INSERT INTO user_data(user_id,type_id,value,hash) VALUES (?,?,?,?),(?,?,?,?)";
$this->db->query($sql, array($user_id, 1, $email, hash($email), //1 - main email user data type
$user_id, 3, $phone, hash($phone)));//3 - phone user data type
} else
return array('error' => #some code error); //problem updating database
# send email with activation link
$this->SendActivationEmail($email,$key);
return array('result_object' => array('user_id' => $user_id));
}
/**
* @param $email
* @param $key
* @return void
*/
public function SendActivationEmail($email,$key) {
$this->load->library('email');
$this->load->helper('url');
$activation_url = site_url("/$some_path/$key");
$this->email->from('some adress');
$this->email->to($email);
$this->email->subject('activation');
# if account is activated - $key is 0
if ($key) {
$this->email->message("Click here to activate your account: $activation_url");
} else {
$this->email->message("Account already has been activated.");
}
$this->email->send();
}
}
2.OutputModel
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class OutputModel extends CI_Model {
private $error = array("error_object"=>array(
"error"=>0)
);
private $result = array();
function __construct() {
// Call the Model constructor
parent::__construct();
}
/**
* @return string jsoned array of $error and $result
*/
function __toString() {
$output=array();
foreach (array($this->error,$this->result) as $value) {
foreach ($value as $subkey=>$subvalue) {
$output[$subkey]=$subvalue;
}
}
$output = json_encode($output, JSON_FORCE_OBJECT);
return $output;
}
/**
* process data into output object
*
* @param array $result "resultObject"
* @return void
*/
function process(array $data) {
if (array_key_exists("result",$data)) {
foreach ($data["result"] as $key=>$value) {
$this->result["result_object"][$key]=$value;
}
}
if (array_key_exists("error",$data)) {
$this->result["error_object"]["error"]=$data['error'];
}
}
}