Created
June 15, 2017 15:23
-
-
Save cullymason/05818b3e3ee7096379ec84b7bc6d81a6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ApiController extends Controller | |
{ | |
public function missingAction($actionID) | |
{ | |
$request_type = $_SERVER['REQUEST_METHOD']; | |
/*------ | |
============== | |
$url STRUCTURE | |
============== | |
example: 'api/categories/1' | |
would translate to: | |
$url = array('api','categories', *1) | |
*id is optional and may not be in the url var | |
-------*/ | |
$url = $_GET['r']; | |
$url = explode("/", $url); | |
$modelName = $url[1]; | |
$model = new EmberModel($modelName); | |
if (count($url) > 2) { | |
$model->setID($url[2]); | |
} | |
//fetch json | |
if ($request_type == "GET") { | |
$model->get($_SERVER['QUERY_STRING']); | |
$model->toJSON(); | |
} // Create New | |
else if ($request_type == "POST" || $request_type == "PUT") { | |
$payload = file_get_contents('php://input'); | |
$payload = json_decode($payload, true); | |
reset($payload); | |
$payloadKey = key($payload); | |
$payload = $payload[$payloadKey]; | |
$model->save($payload); | |
$model->toJSON(); | |
} // Delete | |
else if ($request_type == "DELETE") { | |
$model->trash(); | |
} | |
} | |
public function actionApi() | |
{ | |
echo "main action called"; | |
} | |
public function filters() | |
{ | |
return array( | |
'accessControl', | |
); | |
} | |
public function accessRules() | |
{ | |
return array( | |
array('allow', | |
'actions' => array('adminBadge', 'categories'), | |
'users' => array('@'), | |
'roles' => array('edit_badge') | |
), | |
array('deny', | |
'actions' => array('adminBadge', 'categories') | |
), | |
); | |
} | |
} | |
/*------------------------------- | |
EmberModel Class | |
---------------------------------*/ | |
/** | |
* Class EmberModel | |
*/ | |
class EmberModel | |
{ | |
protected $name = null; | |
protected $substring = null; | |
protected $id = null; | |
protected $hasRelationships = false; | |
protected $relationships = null; | |
protected $hasTransformations = false; | |
protected $transformations = null; | |
protected $results = null; | |
/** | |
* I'd love for appropriate Yii models to extend this class | |
* until then they need to be hardcoded here with this doc: | |
* | |
* Model Properties | |
* ---------------- | |
* Key: pluralized Model Name | |
* - (string) table | |
* - (string) singular: the singular version of the model Name | |
* - (array) transform: replace the column name with another | |
* - (array) relationships: array of all of the relationship | |
* -------------- | |
* - modelName: the plural name of the related model | |
* - type: relationship type (hasMany,hasOne,belongsTo) | |
* - key: (optional) the foreign key | |
* - name: (optional) if the model name is special put it here | |
*/ | |
protected $modelArray = array( | |
'categories' => array( | |
'table' => 'tbl_badge_category', | |
'singular' => 'category', | |
'relationships' => array( | |
array('modelName' => 'badges', 'type' => 'hasMany', 'key' => 'category_id'), | |
array('name' => 'children', 'modelName' => 'categories', 'type' => 'hasMany', 'key' => 'parent') | |
) | |
), | |
'badges' => array( | |
'table' => 'tbl_badges', | |
'singular' => 'badge', | |
'relationships' => array( | |
array('modelName' => 'resources', 'type' => 'hasMany', 'key' => 'badge_id'), | |
array('name' => 'quiz', 'modelName' => 'quizzes', 'type' => 'hasOne', 'key' => 'badge_id'), | |
array('name' => 'mentor', 'modelName' => 'employees', 'type' => 'belongsTo', 'key' => 'mentor_id'), | |
array('name' => 'category', 'modelName' => 'categories', 'type' => 'belongsTo', 'key' => 'category_id') | |
), | |
'transformations' => array( | |
array('type' => 'ignoreProperty', 'target' => array('parent', 'quiz')), | |
array('type' => 'defaultValue', 'target' => array('required' => 0)) | |
) | |
), | |
'resources' => array( | |
'table' => 'tbl_badges_resources', | |
'singular' => 'resource', | |
'relationships' => array( | |
array('name' => 'badge', 'modelName' => 'badges', 'type' => 'belongsTo', 'key' => 'badge_id') | |
) | |
), | |
'employees' => array( | |
'table' => 'tbl_employee', | |
'singular' => 'employee' | |
), | |
'quizzes' => array( | |
'table' => 'tbl_badge_quiz', | |
'singular' => 'quiz', | |
'relationships' => array( | |
array('modelName' => 'questions', 'type' => 'hasMany', 'key' => 'quiz_id'), | |
array('name' => 'badge', 'modelName' => 'badges', 'type' => 'belongsTo', 'key' => 'badge_id') | |
) | |
), | |
'questions' => array( | |
'table' => 'tbl_badge_quiz_question', | |
'singular' => 'question', | |
'relationships' => array( | |
array('modelName' => 'answers', 'type' => 'hasMany', 'key' => 'question_id'), | |
array('name' => 'quiz', 'modelName' => 'quizzes', 'type' => 'belongsTo', 'key' => 'quiz_id') | |
) | |
), | |
'answers' => array( | |
'table' => 'tbl_badge_quiz_answer', | |
'singular' => 'answer', | |
'relationships' => array( | |
array('name' => 'question', 'modelName' => 'questions', 'type' => 'belongsTo', 'key' => 'question_id') | |
), | |
'transformations' => array( | |
array('type' => 'columnName', 'target' => array('content' => 'text')), | |
array('type' => 'defaultValue', 'target' => array('correct_answer' => 0)) | |
) | |
) | |
); | |
/** | |
* constructor that reads $modelArray and builds the class based on the passed $modelName | |
* | |
* @param string $modelName name of the model you would want to collect | |
*/ | |
public function __construct($modelName) | |
{ | |
if ($this->modelExists($modelName)) { | |
$this->name = $modelName; | |
$this->singular = $this->modelArray[$this->name]['singular']; | |
$this->table = $this->modelArray[$this->name]['table']; | |
$this->key = $this->singular . '_id'; | |
if (array_key_exists('relationships', $this->modelArray[$this->name])) { | |
$this->relationships = array(); | |
$this->hasRelationships = true; | |
$this->relationships = $this->parseRelationships(); | |
} else { | |
$this->relationships = false; | |
} | |
if (array_key_exists('transformations', $this->modelArray[$this->name])) { | |
$this->hasTransformations = true; | |
$this->transformations = $this->parseTransformations(); | |
} else { | |
$this->transformations = false; | |
} | |
} | |
} | |
/** | |
* sets the id of the model | |
* | |
* @param number $id id of the model | |
*/ | |
public function setID($id) | |
{ | |
$this->id = $id; | |
} | |
/** | |
* decides if the record needs to be updated or created | |
* | |
* @param array $payload associative array that follows $column=>$value | |
*/ | |
public function save($payload) | |
{ | |
$payload = $this->clean($payload); | |
if (isset($this->id)) { | |
$this->update($payload); | |
} else { | |
$this->create($payload); | |
} | |
} | |
/** | |
* parses the url, loads the substring, then fetches the query results | |
* | |
* @param string $url the entire query string from the url | |
* | |
*/ | |
public function get($url) | |
{ | |
$model = $this->parseURL($url); | |
$this->substring = $model->substring; | |
$this->results = $this->fetch(); | |
} | |
/** | |
* inserts new record into database | |
* | |
* @param array $propertiesArray associative array that follows $column=>$value | |
* | |
*/ | |
protected function create($propertiesArray) | |
{ | |
$command = Yii::app()->db->createCommand(); | |
$result = $command->insert($this->table, $propertiesArray); | |
$this->id = Yii::app()->db->getLastInsertID(); | |
$this->results = $this->fetch(); | |
} | |
/** | |
* updates record in database | |
* | |
* @param array $propertiesArray associative array that follows $column=>$value | |
* | |
*/ | |
protected function update($propertiesArray) | |
{ | |
$id = $this->id; | |
$key = ':' . $this->key; | |
$params = array($key => $id); | |
$command = Yii::app()->db->createCommand(); | |
$result = $command->update($this->table, $propertiesArray, $this->key . '=' . $key, $params); | |
$this->results = $this->fetch(); | |
} | |
/** | |
* deletes a record | |
*/ | |
public function trash() | |
{ | |
$id = $this->id; | |
$key = ':' . $this->key; | |
$params = array($key => $id); | |
$command = Yii::app()->db->createCommand(); | |
$command->delete($this->table, $this->key . '=' . $key, $params); | |
echo "200"; | |
} | |
/** | |
* "cleans" the properties array. removes anything mentioned in the ignore array | |
* for the model. If any of the relationship's type is "belongsTo", the "_id" is added back | |
* that Ember removed. | |
* | |
* @param array $propertiesArray associative array that follows $column=>$value | |
* @return array $propertiesArray | |
*/ | |
protected function clean($propertiesArray) | |
{ | |
if ($this->hasRelationships) { | |
foreach ($this->relationships as $relationship) { | |
if ($relationship->type == 'belongsTo') { | |
$newKey = $relationship->keyName; | |
$tempValue = $propertiesArray[$relationship->name]; | |
$propertiesArray[$newKey] = $tempValue; | |
unset($propertiesArray[$relationship->name]); | |
} | |
} | |
} | |
if ($this->hasTransformations) { | |
foreach ($this->transformations as $transformation) { | |
switch ($transformation->type) { | |
case "columnName": | |
foreach ($transformation->target as $oldColumnName => $newColumnName) { | |
$propertiesArray[$newColumnName] = $propertiesArray[$oldColumnName]; | |
unset($propertiesArray[$oldColumnName]); | |
} | |
break; | |
case "ignoreProperty": | |
foreach ($transformation->target as $property) { | |
unset($propertiesArray[$property]); | |
} | |
break; | |
case "defaultValue": | |
foreach ($transformation->target as $columnName => $defaultValue) { | |
if ($propertiesArray[$columnName] == "" || $propertiesArray[$columnName] == null) { | |
$propertiesArray[$columnName] = $defaultValue; | |
} | |
} | |
break; | |
} | |
} | |
} | |
return $propertiesArray; | |
} | |
/** | |
* reads the "relationship" array out of $modelArray for the given $modelName | |
* and puts sets them into the object $relationships property | |
* | |
* @return array $relationships array of object relationships | |
*/ | |
private function parseRelationships() | |
{ | |
$relationships = $this->modelArray[$this->name]['relationships']; | |
$tempArray = array(); | |
foreach ($relationships as $relationship) { | |
$tempRelationship = new stdClass; | |
// set name | |
if (array_key_exists('name', $relationship)) { | |
$tempRelationship->name = $relationship['name']; | |
} else { | |
if ($relationship['type'] == 'hasMany') { | |
$tempRelationship->name = $relationship['modelName']; | |
} else { | |
$tempRelationship->name = $this->modelArray[$relationship['modelName']]['singular']; | |
} | |
} | |
// relationship model | |
$tempRelationship->model = $relationship['modelName']; | |
// set type | |
$tempRelationship->type = $relationship['type']; | |
// set table | |
$tempRelationship->table = $this->modelArray[$relationship['modelName']]['table']; | |
//set key | |
$tempRelationship->key = $this->modelArray[$relationship['modelName']]['singular'] . '_id'; | |
// set keyName | |
if (array_key_exists('key', $relationship)) { | |
$tempRelationship->keyName = $relationship['key']; | |
} else { | |
$tempKeyName = $relationship['singular']; | |
$tempKeyName = $tempKeyName . '_id'; | |
$tempRelationship->keyName = $tempKeyName; | |
} | |
array_push($tempArray, $tempRelationship); | |
unset($tempRelationship); | |
} | |
$relationships = $tempArray; | |
return $relationships; | |
} | |
/** | |
* Parses a transform array; | |
* | |
* @return array $transformations array of transformation objects | |
**/ | |
protected function parseTransformations() | |
{ | |
$transformations = $this->modelArray[$this->name]['transformations']; | |
$tempArray = array(); | |
foreach ($transformations as $transformation) { | |
$tempTransformation = new stdClass; | |
$tempTransformation->type = $transformation['type']; | |
$tempTransformation->target = $transformation['target']; | |
array_push($tempArray, $tempTransformation); | |
} | |
$transformations = $tempArray; | |
return $transformations; | |
} | |
/** | |
* determines if the given model exists | |
* | |
* @param string $model model name (plural) | |
* @return boolean | |
*/ | |
private function modelExists($model) | |
{ | |
if (array_key_exists($model, $this->modelArray)) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* Return data to browser as JSON and end application. | |
* | |
* @internal param array $data | |
*/ | |
public function toJSON() | |
{ | |
header('Content-type: application/json'); | |
if ($this->id) { | |
$name = $this->singular; | |
} else { | |
$name = $this->name; | |
} | |
$results = $this->results; | |
$results = CJSON::encode(array($name => $results)); | |
echo $results; | |
foreach (Yii::app()->log->routes as $route) { | |
if ($route instanceof CWebLogRoute) { | |
$route->enabled = false; // disable any weblogroutes | |
} | |
} | |
Yii::app()->end(); | |
} | |
/** | |
* runs select sql statement against model properties | |
* returns array $results | |
*/ | |
private function fetch() | |
{ | |
$results = false; | |
if ($this->id) { | |
$results = Yii::app()->db->createCommand()->select('*')->from($this->table)->where($this->key . '=' . $this->id)->queryRow(); | |
if ($this->hasRelationships) { | |
$relationships = $this->fetchRelationships($this->id); | |
foreach ($relationships as $relationship => $value) { | |
$results[$relationship] = $value; | |
} | |
} | |
} else if ($this->substring) { | |
$results = Yii::app()->db->createCommand()->select('*')->from($this->table)->where(array('in', $this->key, $this->substring['ids']))->queryAll(); | |
if ($this->hasRelationships) { | |
$tempArray = array(); | |
foreach ($results as $result) { | |
$id = $result[$this->key]; | |
$relationships = $this->fetchRelationships($id); | |
if (!empty($relationships)) { | |
foreach ($relationships as $relationship => $value) { | |
$result[$relationship] = $value; | |
array_push($tempArray, $result); | |
} | |
$results = $tempArray; | |
} | |
} | |
} | |
} else { | |
$results = Yii::app()->db->createCommand()->selectDistinct('*')->from($this->table)->queryAll(); | |
if ($this->hasRelationships) { | |
$tempArray = array(); | |
foreach ($results as $result) { | |
$id = $result[$this->key]; | |
$relationships = $this->fetchRelationships($id); | |
foreach ($relationships as $relationship => $value) { | |
$result[$relationship] = $value; | |
array_push($tempArray, $result); | |
} | |
} | |
$results = $tempArray; | |
} | |
} | |
return $results; | |
} | |
/** | |
* fetches either an array of relationship ids or just one | |
* | |
* @param number $id | |
* @return array $relationshipArray | |
*/ | |
private function fetchRelationships($id) | |
{ | |
/* | |
SELECT $key FROM $table WHERE $keyname = $id | |
*/ | |
$relationshipArray = array(); | |
foreach ($this->relationships as $relationship) { | |
if ($relationship->type == "hasMany") { | |
$results = Yii::app()->db->createCommand() | |
->select($relationship->key) | |
->from($relationship->table) | |
->where($relationship->keyName . '=' . $id)->queryAll(); | |
$relationshipArray[$relationship->name] = array(); | |
foreach ($results as $result) { | |
foreach ($result as $r) { | |
array_push($relationshipArray[$relationship->name], $r); | |
} | |
} | |
} else if ($relationship->type == "hasOne") { | |
$result = Yii::app()->db->createCommand() | |
->select($relationship->key) | |
->from($relationship->table) | |
->where($relationship->keyName . '=' . $id)->queryRow(); | |
$relationshipArray[$relationship->name] = $result[$relationship->key]; | |
} | |
} | |
return $relationshipArray; | |
} | |
/** | |
* reads url and returns a model containing the $substring | |
* @param array $url | |
* @return object $model | |
*/ | |
private function parseURL($url) | |
{ | |
$model = new stdClass(); | |
parse_str($url, $url); | |
$r = $url['r']; | |
$r = explode("/", $r); | |
if (count($url) > 1) { | |
unset($url['r']); | |
$tempArray = array(); | |
foreach ($url as $key => $value) { | |
$tempArray[$key] = $value; | |
} | |
$model->substring = $tempArray; | |
} else { | |
$model->substring = false; | |
} | |
return $model; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment