diff --git a/plugins/ahmadfatoni/apigenerator/Plugin.php b/plugins/ahmadfatoni/apigenerator/Plugin.php
new file mode 100644
index 000000000..575a4fdf1
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/Plugin.php
@@ -0,0 +1,18 @@
+ October CMS plugin to build RESTful APIs.
+
+## Features
+
+ - Auto generate routes
+ - Auto Generate Controller (CRUD)
+ - Support relationship restful API
+
+## Install
+```
+composer require AhmadFatoni.ApiGenerator
+```
+
+## Usage
+
+### Form
+- API Name : Name of your API module
+- Base Endpoint : Base endpoint of your API, ex : api/v1/modulename
+- Short Description : Describe your API
+- Model : select model that will be created API
+- Custom Condition : Build customer response using JSON modeling
+
+### Custom Condition Example
+```
+{
+ 'fillable': 'id,title,content',
+ 'relation': [{
+ 'name': 'user',
+ 'fillable': 'id,first_name'
+ }, {
+ 'name': 'categories',
+ 'fillable': 'id,name
+ }]
+}
+```
+* please replace single quote with quote
+
+## Contribute
+
+Pull Requests accepted.
+
+## Contact
+
+You can communicate with me using [linkedin](https://www.linkedin.com/in/ahmad-fatoni)
+
+## License
+The OctoberCMS platform is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
diff --git a/plugins/ahmadfatoni/apigenerator/composer.json b/plugins/ahmadfatoni/apigenerator/composer.json
new file mode 100644
index 000000000..889212022
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/composer.json
@@ -0,0 +1,8 @@
+{
+ "name": "ahmadfatoni/apigenerator-plugin",
+ "type": "october-plugin",
+ "description": "None",
+ "require": {
+ "composer/installers": "~1.0"
+ }
+}
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/ApiGeneratorController.php b/plugins/ahmadfatoni/apigenerator/controllers/ApiGeneratorController.php
new file mode 100644
index 000000000..1eea0a4c4
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/ApiGeneratorController.php
@@ -0,0 +1,336 @@
+files = $files;
+ }
+
+ /**
+ * delete selected data (multiple delete)
+ * @return [type] [description]
+ */
+ public function index_onDelete()
+ {
+ if (($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds)) {
+
+ foreach ($checkedIds as $id) {
+ if ((!$item = ApiGenerator::find($id)))
+ continue;
+ $name = $item->name;
+ if($item->delete()){
+ $this->deleteApi($name);
+ }
+ }
+
+ Flash::success('Successfully deleted those data.');
+ }
+
+ return $this->listRefresh();
+ }
+
+ /**
+ * generate API
+ * @param Request $request [description]
+ * @return [type] [description]
+ */
+ public function generateApi(Request $request){
+
+ $data['model'] = $request->model;
+ $modelname = explode("\\", $request->model);
+ $modelname = $modelname[count($modelname)-1];
+ $data['modelname'] = $modelname;
+ $data['controllername'] = str_replace(" ", "", $request->name);
+ $data['endpoint'] = $request->endpoint;
+ $data['custom_format'] = $request->custom_format;
+
+ if( strpos($data['controllername'], ".") OR strpos($data['controllername'], "/") ){
+
+ Flash::success('Failed to create data, invalid API name.');
+ return Redirect::to( Backend::url($this->homePage));
+
+ }
+
+ if( isset($request->id) ){
+ $this->deleteApi($request->oldname, 'false');
+ }
+
+ $this->files->put(__DIR__ . $this->path . $data['controllername'].'Controller.php', $this->compile($data));
+
+ $this->files->put(__DIR__ . '/'.'../routes.php', $this->compileRoute($data));
+
+ return Redirect::to( Backend::url($this->homePage));
+
+ }
+
+ /**
+ * delete available API
+ * @param [type] $name [description]
+ * @param [type] $redirect [description]
+ * @return [type] [description]
+ */
+ public function deleteApi($name, $redirect = null){
+
+ $fileLocation = __DIR__ . $this->path.$name;
+ $fileLocation = str_replace(".", "", $fileLocation);
+
+ if( ! file_exists($fileLocation.'Controller.php') ){
+
+ Flash::success('Failed to delete data, invalid file location.');
+ return Redirect::to( Backend::url($this->homePage));
+
+ }
+
+ if( strpos( strtolower($name), 'apigenerator' ) === false){
+ $data = [];
+
+ //generate new route
+ $this->files->put(__DIR__ . '/'.'../routes.php', $this->compileRoute($data));
+
+ //remove controller
+ if (file_exists( __DIR__ . $this->path.$name.'Controller.php' )) {
+
+ unlink(__DIR__ . $this->path.$name.'Controller.php');
+
+ }
+
+ if( $redirect != null ){
+ return 'success without redirect';
+ }
+ }
+
+ return Redirect::to( Backend::url($this->homePage));
+
+ }
+
+ public function updateApi($name){
+
+ }
+
+ /**
+ * compile controller from template
+ * @param [type] $data [description]
+ * @return [type] [description]
+ */
+ public function compile($data){
+ if( $data['custom_format'] != ''){
+
+ $template = $this->files->get(__DIR__ .'/../template/customcontroller.dot');
+ $template = $this->replaceAttribute($template, $data);
+ $template = $this->replaceCustomAttribute($template, $data);
+ }else{
+ $template = $this->files->get(__DIR__ .'/../template/controller.dot');
+ $template = $this->replaceAttribute($template, $data);
+ }
+ return $template;
+ }
+
+ /**
+ * replace attribute
+ * @param [type] $template [description]
+ * @param [type] $data [description]
+ * @return [type] [description]
+ */
+ public function replaceAttribute($template, $data){
+ if( isset( $data['model'] ) ){
+ $template = str_replace('{{model}}', $data['model'], $template);
+ }
+ $template = str_replace('{{modelname}}', $data['modelname'], $template);
+ $template = str_replace('{{controllername}}', $data['controllername'], $template);
+ return $template;
+ }
+
+ /**
+ * replace custom attribute
+ * @param [type] $template [description]
+ * @param [type] $data [description]
+ * @return [type] [description]
+ */
+ public function replaceCustomAttribute($template, $data){
+
+ $arr = str_replace('\t', '', $data['custom_format']);
+ $arr = json_decode($arr);
+ $select = str_replace('
', '', $this->compileOpenIndexFunction($data['modelname'], 'index'));
+ $show = str_replace('
', '', $this->compileOpenIndexFunction($data['modelname'], 'show'));
+ $fillableParent = '';
+
+ if( isset($arr->fillable) AND $arr->fillable != null ) {
+ $fillableParent = $this->compileFillableParent($arr->fillable);
+ }
+
+ if( isset($arr->relation) AND $arr->relation != null AND is_array($arr->relation) AND count($arr->relation) > 0) {
+ $select .= str_replace('
', '', $this->compileFillableChild($arr->relation));
+ $show .= str_replace('
', '', $this->compileFillableChild($arr->relation));
+ }
+
+ $select .= "->select(".$fillableParent.")";
+ $show .= "->select(".$fillableParent.")->where('id', '=', \$id)->first();";
+
+ ( $fillableParent != '') ? $select .= "->get()->toArray();" : $select .= "->toArray();" ;
+
+ $closeFunction = str_replace('
', '', nl2br(
+ "
+ return \$this->helpers->apiArrayResponseBuilder(200, 'success', \$data);
+ }"));
+ $select .= $closeFunction;
+ $show .= $closeFunction;
+
+ $template = str_replace('{{select}}', $select, $template);
+ $template = str_replace('{{show}}', $show, $template);
+
+ return $template;
+ }
+
+ public function compileOpenIndexFunction($modelname, $type){
+ if( $type == 'index'){
+ return nl2br("
+ public function index(){
+ \$data = \$this->".$modelname);
+ }else{
+ return nl2br("
+ public function show(\$id){
+ \$data = \$this->".$modelname);
+ }
+
+ }
+
+ public function compileFillableParent($fillable){
+
+ $fillableParentArr = explode(",", $fillable);
+ $fillableParent = '';
+
+ foreach ($fillableParentArr as $key) {
+
+ $fillableParent .= ",'".$key."'";
+
+ }
+
+ $fillableParent = substr_replace($fillableParent, '', 0 , 1);
+
+ return $fillableParent;
+ }
+
+ public function compileFillableChild($fillable){
+
+ $select = "->with(array(";
+
+ foreach ($fillable as $key) {
+
+ $fillableChild = "";
+
+ if( isset($key->fillable) AND $key->fillable != null ){
+ $fillableChildArr = explode(",", $key->fillable);
+
+
+ foreach ($fillableChildArr as $key2) {
+
+ $fillableChild .= ",'".$key2."'";
+
+ }
+
+ $fillableChild = substr_replace($fillableChild, '', 0 , 1);
+ }
+
+ $select .= nl2br(
+ "
+ '".$key->name."'=>function(\$query){
+ \$query->select(".$fillableChild.");
+ },");
+
+ }
+
+ $select .= " ))";
+
+ return $select;
+ }
+
+ public function compileRoute($data){
+
+ $oldData = ApiGenerator::all();
+ $routeList = "";
+
+ if( count($oldData) > 0 ){
+
+ $routeList .= $this->parseRouteOldData($oldData, $data);
+
+ }
+
+ if( count($data) > 0 ){
+ $data['modelname'] = $data['endpoint'];
+ if( $data['modelname'][0] == "/" ){
+ $data['modelname'] = substr_replace($data['modelname'], '', 0 , 1);
+ }
+ $routeList .= $this->parseRoute($data);
+ }
+
+ $route = $this->files->get(__DIR__ .'/../template/routes.dot');
+ $route = str_replace('{{route}}', $routeList, $route);
+
+ return $route;
+
+ }
+
+ public function parseRouteOldData($oldData, $data = null){
+
+ $routeList = "";
+
+ if( count($data) == 0 ) $data['modelname']='';
+
+ foreach ( $oldData as $key ) {
+
+ $modelname = explode("\\", $key->model);
+ $modelname = $modelname[count($modelname)-1];
+ $old['modelname'] = $key->endpoint;
+ $old['controllername'] = $key->name;
+
+ if( $data['modelname'] != $modelname ){
+
+ if( $old['modelname'][0] == "/" ){
+ $old['modelname'] = substr_replace($old['modelname'], '', 0 , 1);
+ }
+
+ $routeList .= $this->parseRoute($old);
+ }
+ }
+
+ return $routeList;
+
+ }
+
+ public function parseRoute($data){
+
+ $template = $this->files->get(__DIR__ .'/../template/route.dot');
+ $template = $this->replaceAttribute($template, $data);
+ return $template;
+ }
+
+
+ public static function getAfterFilters() {return [];}
+ public static function getBeforeFilters() {return [];}
+ public function callAction($method, $parameters=false) {
+ return call_user_func_array(array($this, $method), $parameters);
+ }
+}
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/api/readme.txt b/plugins/ahmadfatoni/apigenerator/controllers/api/readme.txt
new file mode 100644
index 000000000..f972e8de0
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/api/readme.txt
@@ -0,0 +1 @@
+api controller here
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/_list_toolbar.htm b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/_list_toolbar.htm
new file mode 100644
index 000000000..82a362239
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/_list_toolbar.htm
@@ -0,0 +1,18 @@
+
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/_reorder_toolbar.htm b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/_reorder_toolbar.htm
new file mode 100644
index 000000000..59b78d088
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/_reorder_toolbar.htm
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_form.yaml b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_form.yaml
new file mode 100644
index 000000000..9317c6bd1
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_form.yaml
@@ -0,0 +1,10 @@
+name: ApiGeneratorController
+form: $/ahmadfatoni/apigenerator/models/apigenerator/fields.yaml
+modelClass: AhmadFatoni\ApiGenerator\Models\ApiGenerator
+defaultRedirect: ahmadfatoni/apigenerator/apigeneratorcontroller
+create:
+ redirect: 'ahmadfatoni/apigenerator/apigeneratorcontroller/update/:id'
+ redirectClose: ahmadfatoni/apigenerator/apigeneratorcontroller
+update:
+ redirect: ahmadfatoni/apigenerator/apigeneratorcontroller
+ redirectClose: ahmadfatoni/apigenerator/apigeneratorcontroller
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_list.yaml b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_list.yaml
new file mode 100644
index 000000000..d36a63f51
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_list.yaml
@@ -0,0 +1,11 @@
+list: $/ahmadfatoni/apigenerator/models/apigenerator/columns.yaml
+modelClass: AhmadFatoni\ApiGenerator\Models\ApiGenerator
+title: ApiGeneratorController
+noRecordsMessage: 'backend::lang.list.no_records'
+showSetup: true
+showCheckboxes: true
+toolbar:
+ buttons: list_toolbar
+ search:
+ prompt: 'backend::lang.list.search_prompt'
+recordUrl: 'ahmadfatoni/apigenerator/apigeneratorcontroller/update/:id'
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_reorder.yaml b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_reorder.yaml
new file mode 100644
index 000000000..70fda7be8
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/config_reorder.yaml
@@ -0,0 +1,4 @@
+title: ApiGeneratorController
+modelClass: AhmadFatoni\ApiGenerator\Models\ApiGenerator
+toolbar:
+ buttons: reorder_toolbar
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/create.htm b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/create.htm
new file mode 100644
index 000000000..22322c523
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/create.htm
@@ -0,0 +1,97 @@
+
+
+
+
+fatalError): ?>
+
+ = Form::open(['class' => 'layout']) ?>
+
+
+ = $this->formRender() ?>
+
+
+
+
+
+
+ = Form::close() ?>
+
+
+
+
+ = e(trans($this->fatalError)) ?>
+ = e(trans('backend::lang.form.return_to_list')) ?>
+
+
+
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/index.htm b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/index.htm
new file mode 100644
index 000000000..ea43a3636
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/index.htm
@@ -0,0 +1 @@
+= $this->listRender() ?>
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/preview.htm b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/preview.htm
new file mode 100644
index 000000000..f259af345
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/preview.htm
@@ -0,0 +1,22 @@
+
+
+
+
+fatalError): ?>
+
+
+ = $this->formRenderPreview() ?>
+
+
+
+ = e($this->fatalError) ?>
+
+
+
+
+ = e(trans('backend::lang.form.return_to_list')) ?>
+
+
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/reorder.htm b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/reorder.htm
new file mode 100644
index 000000000..9813ab46a
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/reorder.htm
@@ -0,0 +1,8 @@
+
+
+
+
+= $this->reorderRender() ?>
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/update.htm b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/update.htm
new file mode 100644
index 000000000..dc6594a46
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/controllers/apigeneratorcontroller/update.htm
@@ -0,0 +1,133 @@
+
+
+
+
+fatalError): ?>
+
+ = Form::open(['class' => 'layout']) ?>
+
+
+ = $this->formRender() ?>
+
+
+
+
+ = Form::close() ?>
+
+
+ = e(trans($this->fatalError)) ?>
+ = e(trans('backend::lang.form.return_to_list')) ?>
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/helpers/Helpers.php b/plugins/ahmadfatoni/apigenerator/helpers/Helpers.php
new file mode 100644
index 000000000..1145f7f7a
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/helpers/Helpers.php
@@ -0,0 +1,19 @@
+ (isset($statusCode)) ? $statusCode : 500,
+ 'message' => (isset($message)) ? $message : 'error'
+ ];
+ if (count($data) > 0) {
+ $arr['data'] = $data;
+ }
+
+ return response()->json($arr, $arr['status_code']);
+ //return $arr;
+
+ }
+}
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/lang/en/lang.php b/plugins/ahmadfatoni/apigenerator/lang/en/lang.php
new file mode 100644
index 000000000..9ade59ec2
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/lang/en/lang.php
@@ -0,0 +1,6 @@
+ [
+ 'name' => 'API-Generator',
+ 'description' => 'Generate API base on Builder Plugin'
+ ]
+];
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/models/ApiGenerator.php b/plugins/ahmadfatoni/apigenerator/models/ApiGenerator.php
new file mode 100644
index 000000000..531bfd111
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/models/ApiGenerator.php
@@ -0,0 +1,76 @@
+ 'required|unique:ahmadfatoni_apigenerator_data,name|regex:/^[\pL\s\-]+$/u',
+ 'endpoint' => 'required|unique:ahmadfatoni_apigenerator_data,endpoint',
+ 'custom_format' => 'json'
+ ];
+
+ public $customMessages = [
+ 'custom_format.json' => 'Invalid Json Format Custom Condition'
+ ];
+
+ /*
+ * Disable timestamps by default.
+ * Remove this line if timestamps are defined in the database table.
+ */
+ public $timestamps = false;
+
+ /**
+ * @var string The database table used by the model.
+ */
+ public $table = 'ahmadfatoni_apigenerator_data';
+
+ /**
+ * get model List
+ * @return [type] [description]
+ */
+ public function getModelOptions(){
+
+ return ComponentHelper::instance()->listGlobalModels();
+ }
+
+ /**
+ * [setCustomFormatAttribute description]
+ * @param [type] $value [description]
+ */
+ public function setCustomFormatAttribute($value){
+
+ $json = str_replace('\t', '', $value);
+ $json = json_decode($json);
+
+ if( $json != null){
+
+ if( ! isset($json->fillable) AND ! isset($json->relation) ){
+
+ return $this->attributes['custom_format'] = 'invalid format';
+
+ }
+
+ if( isset($json->relation) AND $json->relation != null ){
+ foreach ($json->relation as $key) {
+ if( !isset($key->name) OR $key->name == null ){
+ return $this->attributes['custom_format'] = 'invalid format';
+ }
+ }
+ }
+ }
+
+ return $this->attributes['custom_format'] = $value;
+
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/models/apigenerator/columns.yaml b/plugins/ahmadfatoni/apigenerator/models/apigenerator/columns.yaml
new file mode 100644
index 000000000..58ce8eb61
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/models/apigenerator/columns.yaml
@@ -0,0 +1,9 @@
+columns:
+ name:
+ label: 'API NAME'
+ type: text
+ searchable: true
+ sortable: true
+ endpoint:
+ label: 'BASE ENDPOINT'
+ type: text
diff --git a/plugins/ahmadfatoni/apigenerator/models/apigenerator/fields.yaml b/plugins/ahmadfatoni/apigenerator/models/apigenerator/fields.yaml
new file mode 100644
index 000000000..a8e6e0bce
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/models/apigenerator/fields.yaml
@@ -0,0 +1,33 @@
+fields:
+ name:
+ label: 'API Name'
+ oc.commentPosition: ''
+ span: auto
+ placeholder: 'Name of your API'
+ required: 1
+ type: text
+ endpoint:
+ label: 'Base Endpoint'
+ oc.commentPosition: ''
+ span: auto
+ placeholder: api/v1/modulename
+ required: 1
+ type: text
+ description:
+ label: 'Short Description'
+ oc.commentPosition: ''
+ span: auto
+ placeholder: 'Descript your API'
+ type: text
+ model:
+ label: 'Select Model'
+ oc.commentPosition: ''
+ span: auto
+ required: 1
+ type: dropdown
+ custom_format:
+ label: 'Custom Condition (Fillable and Relation)'
+ size: large
+ oc.commentPosition: ''
+ span: full
+ type: textarea
diff --git a/plugins/ahmadfatoni/apigenerator/plugin.yaml b/plugins/ahmadfatoni/apigenerator/plugin.yaml
new file mode 100644
index 000000000..598021df5
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/plugin.yaml
@@ -0,0 +1,17 @@
+plugin:
+ name: 'ahmadfatoni.apigenerator::lang.plugin.name'
+ description: 'ahmadfatoni.apigenerator::lang.plugin.description'
+ author: AhmadFatoni
+ icon: oc-icon-bolt
+ homepage: ''
+navigation:
+ api-generator:
+ label: 'API Generator'
+ url: ahmadfatoni/apigenerator/apigeneratorcontroller
+ icon: icon-cogs
+ permissions:
+ - ahmadfatoni.apigenerator.manage
+permissions:
+ ahmadfatoni.apigenerator.manage:
+ tab: 'API Generator'
+ label: 'Manage the API Generator'
diff --git a/plugins/ahmadfatoni/apigenerator/routes.php b/plugins/ahmadfatoni/apigenerator/routes.php
new file mode 100644
index 000000000..3b728326c
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/routes.php
@@ -0,0 +1,8 @@
+ 'fatoni.generate.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@generateApi'));
+Route::post('fatoni/update/api/{id}', array('as' => 'fatoni.update.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@updateApi'));
+Route::get('fatoni/delete/api/{id}', array('as' => 'fatoni.delete.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@deleteApi'));
+
+Route::resource('halo', 'AhmadFatoni\ApiGenerator\Controllers\API\haloController', ['except' => ['destroy', 'create', 'edit']]);
+Route::get('halo/{id}/delete', ['as' => 'halo.delete', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\API\haloController@destroy']);
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/template/controller.dot b/plugins/ahmadfatoni/apigenerator/template/controller.dot
new file mode 100644
index 000000000..ff20ea3aa
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/template/controller.dot
@@ -0,0 +1,99 @@
+{{modelname}} = ${{modelname}};
+ $this->helpers = $helpers;
+ }
+
+ public function index(){
+
+ $data = $this->{{modelname}}->all()->toArray();
+
+ return $this->helpers->apiArrayResponseBuilder(200, 'success', $data);
+ }
+
+ public function show($id){
+
+ $data = $this->{{modelname}}::find($id);
+
+ if ($data){
+ return $this->helpers->apiArrayResponseBuilder(200, 'success', [$data]);
+ } else {
+ $this->helpers->apiArrayResponseBuilder(404, 'not found', ['error' => 'Resource id=' . $id . ' could not be found']);
+ }
+
+ }
+
+ public function store(Request $request){
+
+ $arr = $request->all();
+
+ while ( $data = current($arr)) {
+ $this->{{modelname}}->{key($arr)} = $data;
+ next($arr);
+ }
+
+ $validation = Validator::make($request->all(), $this->{{modelname}}->rules);
+
+ if( $validation->passes() ){
+ $this->{{modelname}}->save();
+ return $this->helpers->apiArrayResponseBuilder(201, 'created', ['id' => $this->{{modelname}}->id]);
+ }else{
+ return $this->helpers->apiArrayResponseBuilder(400, 'fail', $validation->errors() );
+ }
+
+ }
+
+ public function update($id, Request $request){
+
+ $status = $this->{{modelname}}->where('id',$id)->update($data);
+
+ if( $status ){
+
+ return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been updated successfully.');
+
+ }else{
+
+ return $this->helpers->apiArrayResponseBuilder(400, 'bad request', 'Error, data failed to update.');
+
+ }
+ }
+
+ public function delete($id){
+
+ $this->{{modelname}}->where('id',$id)->delete();
+
+ return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been deleted successfully.');
+ }
+
+ public function destroy($id){
+
+ $this->{{modelname}}->where('id',$id)->delete();
+
+ return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been deleted successfully.');
+ }
+
+
+ public static function getAfterFilters() {return [];}
+ public static function getBeforeFilters() {return [];}
+ public static function getMiddleware() {return [];}
+ public function callAction($method, $parameters=false) {
+ return call_user_func_array(array($this, $method), $parameters);
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/template/controller.php b/plugins/ahmadfatoni/apigenerator/template/controller.php
new file mode 100644
index 000000000..f78dde065
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/template/controller.php
@@ -0,0 +1,35 @@
+{{modelname}} = ${{modelname}};
+ }
+
+ public static function getAfterFilters() {return [];}
+ public static function getBeforeFilters() {return [];}
+ public static function getMiddleware() {return [];}
+ public function callAction($method, $parameters=false) {
+ return call_user_func_array(array($this, $method), $parameters);
+ }
+
+ // public function create(Request $request){
+
+ // $arr = $request->all();
+
+ // while ( $data = current($arr)) {
+ // $this->
+ // }
+ // return json_encode($this->{{modelname}}->store($request));
+
+ // }
+}
diff --git a/plugins/ahmadfatoni/apigenerator/template/customcontroller.dot b/plugins/ahmadfatoni/apigenerator/template/customcontroller.dot
new file mode 100644
index 000000000..be5cf6ff2
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/template/customcontroller.dot
@@ -0,0 +1,83 @@
+{{modelname}} = ${{modelname}};
+ $this->helpers = $helpers;
+ }
+
+ {{select}}
+
+ {{show}}
+
+ public function store(Request $request){
+
+ $arr = $request->all();
+
+ while ( $data = current($arr)) {
+ $this->{{modelname}}->{key($arr)} = $data;
+ next($arr);
+ }
+
+ $validation = Validator::make($request->all(), $this->{{modelname}}->rules);
+
+ if( $validation->passes() ){
+ $this->{{modelname}}->save();
+ return $this->helpers->apiArrayResponseBuilder(201, 'created', ['id' => $this->{{modelname}}->id]);
+ }else{
+ return $this->helpers->apiArrayResponseBuilder(400, 'fail', $validation->errors() );
+ }
+
+ }
+
+ public function update($id, Request $request){
+
+ $status = $this->{{modelname}}->where('id',$id)->update($data);
+
+ if( $status ){
+
+ return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been updated successfully.');
+
+ }else{
+
+ return $this->helpers->apiArrayResponseBuilder(400, 'bad request', 'Error, data failed to update.');
+
+ }
+ }
+
+ public function delete($id){
+
+ $this->{{modelname}}->where('id',$id)->delete();
+
+ return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been deleted successfully.');
+ }
+
+ public function destroy($id){
+
+ $this->{{modelname}}->where('id',$id)->delete();
+
+ return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been deleted successfully.');
+ }
+
+
+ public static function getAfterFilters() {return [];}
+ public static function getBeforeFilters() {return [];}
+ public static function getMiddleware() {return [];}
+ public function callAction($method, $parameters=false) {
+ return call_user_func_array(array($this, $method), $parameters);
+ }
+
+}
diff --git a/plugins/ahmadfatoni/apigenerator/template/route.dot b/plugins/ahmadfatoni/apigenerator/template/route.dot
new file mode 100644
index 000000000..515cb53c9
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/template/route.dot
@@ -0,0 +1,3 @@
+
+Route::resource('{{modelname}}', 'AhmadFatoni\ApiGenerator\Controllers\API\{{controllername}}Controller', ['except' => ['destroy', 'create', 'edit']]);
+Route::get('{{modelname}}/{id}/delete', ['as' => '{{modelname}}.delete', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\API\{{controllername}}Controller@destroy']);
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/template/routes.dot b/plugins/ahmadfatoni/apigenerator/template/routes.dot
new file mode 100644
index 000000000..ddafe5901
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/template/routes.dot
@@ -0,0 +1,6 @@
+ 'fatoni.generate.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@generateApi'));
+Route::post('fatoni/update/api/{id}', array('as' => 'fatoni.update.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@updateApi'));
+Route::get('fatoni/delete/api/{id}', array('as' => 'fatoni.delete.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@deleteApi'));
+{{route}}
\ No newline at end of file
diff --git a/plugins/ahmadfatoni/apigenerator/updates/builder_table_create_ahmadfatoni_apigenerator_data.php b/plugins/ahmadfatoni/apigenerator/updates/builder_table_create_ahmadfatoni_apigenerator_data.php
new file mode 100644
index 000000000..44cdc81e3
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/updates/builder_table_create_ahmadfatoni_apigenerator_data.php
@@ -0,0 +1,26 @@
+engine = 'InnoDB';
+ $table->increments('id');
+ $table->string('name');
+ $table->string('endpoint');
+ $table->string('model');
+ $table->string('description')->nullable();
+ $table->text('custom_format')->nullable();
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('ahmadfatoni_apigenerator_data');
+ }
+}
diff --git a/plugins/ahmadfatoni/apigenerator/updates/version.yaml b/plugins/ahmadfatoni/apigenerator/updates/version.yaml
new file mode 100644
index 000000000..966ff307a
--- /dev/null
+++ b/plugins/ahmadfatoni/apigenerator/updates/version.yaml
@@ -0,0 +1,15 @@
+1.0.1:
+ - 'Initialize plugin.'
+1.0.2:
+ - 'Database implementation'
+1.0.3:
+ - 'add builder plugin on requirements dependency'
+ - builder_table_create_ahmadfatoni_apigenerator_data.php
+1.0.4:
+ - 'fixing bug on PHP 7'
+1.0.5:
+ - 'fixing bug on request delete data'
+1.0.6:
+ - 'fixing bug on generate endpoint'
+1.0.7:
+ - 'fixing bug on October CMS v1.0.456'
\ No newline at end of file