PageRenderTime 23ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Controller/AppController.php

https://gitlab.com/vortexadventures/void
PHP | 292 lines | 252 code | 38 blank | 2 comment | 33 complexity | 35f26b629c60dfbb111ffb96f8781499 MD5 | raw file
  1. <?php
  2. namespace App\Controller;
  3. use App\Utility\AuthState;
  4. use Cake\Controller\Controller;
  5. use Cake\Core\Configure;
  6. use Cake\Datasource\ConnectionManager;
  7. use Cake\Error\ErrorHandler;
  8. use Cake\Event\Event;
  9. use Cake\Http\Exception\BadRequestException;
  10. use Cake\Utility\Inflector;
  11. use Crud\Error\Exception\ValidationException;
  12. use Crud\Controller\ControllerTrait;
  13. class AppController
  14. extends Controller
  15. {
  16. use ControllerTrait;
  17. protected $searchFields = [ ];
  18. public function initialize()
  19. {
  20. parent::initialize();
  21. $this->loadComponent('Crud.Crud',
  22. [ 'listeners' => ['Crud.RelatedModels']
  23. ]);
  24. $this->loadComponent('Auth',
  25. [ 'storage' => 'Memory'
  26. , 'authenticate' =>
  27. [ 'Form' =>
  28. [ 'userModel' => 'Players'
  29. , 'fields' => [ 'username' => 'id' ]
  30. ]
  31. , 'ADmad/JwtAuth.Jwt' =>
  32. [ 'userModel' => 'Players'
  33. , 'fields' => [ 'username' => 'id' ]
  34. , 'parameter' => 'token'
  35. , 'queryDatasource' => true
  36. , 'unauthenticatedException' => '\Cake\Http\Exception\ForbiddenException'
  37. ] ]
  38. , 'authorize' => ['Controller']
  39. , 'unauthorizedRedirect' => false
  40. , 'checkAuthIn' => 'Controller.initialize'
  41. , 'loginAction' => '/auth/login'
  42. , 'logoutRedirect' => '/'
  43. ]);
  44. $this->viewBuilder()->setClassName('Api');
  45. $arr = ['exceptionRenderer' => 'App\Error\ApiExceptionRenderer']
  46. + Configure::read('Error');
  47. (new ErrorHandler($arr))->register();
  48. $this->response->compress();
  49. if(!$this->request->is('POST')) {
  50. $data = $this->request->input([$this, 'parseRequestInput']);
  51. foreach($data as $key => $val) {
  52. $this->request = $this->request->withData($key, $val);
  53. }
  54. }
  55. }
  56. public function implementedEvents()
  57. {
  58. $events = parent::implementedEvents();
  59. $events['Crud.beforeHandle'] = 'CrudBeforeHandle';
  60. $events['Crud.afterSave'] = 'CrudAfterSave';
  61. $events['Crud.afterDelete'] = 'CrudAfterDelete';
  62. $events['Crud.beforeRedirect'] = 'CrudBeforeRedirect';
  63. return $events;
  64. }
  65. public function isAuthorized($user)
  66. {
  67. AuthState::initialize($this->Auth, $this->wantAuthUser());
  68. $auths = $this->Crud->action()->getConfig('auth') ?: ['super'];
  69. return AuthState::hasAuth($auths);
  70. }
  71. protected function wantAuthUser()
  72. {
  73. return $this->request->getParam('plin');
  74. }
  75. public function paginate($query = null, array $settings = [])
  76. {
  77. $action = $this->request->getParam('action');
  78. $nested = strcmp(substr($action, -5, 5), 'Index') === 0;
  79. if($nested && isset($this->viewVars['parent'])) {
  80. $key = Inflector::singularize(substr($action, 0, -5)).'_id';
  81. $query->where([$key => $this->viewVars['parent']->id]);
  82. }
  83. return $query->all();
  84. }
  85. public function parseRequestInput($input)
  86. {
  87. if(empty($input)) {
  88. return [];
  89. }
  90. $json = json_decode($input, true);
  91. $error = json_last_error();
  92. if($error != JSON_ERROR_NONE) {
  93. $msg = sprintf("Failed to parse json, error: %s '%s'"
  94. , $error, json_last_error_msg());
  95. throw new BadRequestException($msg);
  96. }
  97. return $json;
  98. }
  99. public function CrudBeforeHandle(Event $event)
  100. {
  101. $action = $this->request->getParam('action');
  102. if(strcmp(substr($action, -3, 3), 'add') == 0
  103. || strcmp(substr($action, -4, 4), 'edit') == 0) {
  104. # remove stuff that's not in the db
  105. foreach($this->request->getData() as $key => $value) {
  106. if(!$this->loadModel()->hasField($key))
  107. $this->request = $this->request->withoutData($key);
  108. }
  109. # these can never be set through the rest-api
  110. $this->request = $this->request->withoutData('created');
  111. $this->request = $this->request->withoutData('creator_id');
  112. $this->request = $this->request->withoutData('modified');
  113. $this->request = $this->request->withoutData('modifier_id');
  114. }
  115. if(strcmp(substr($action, -5, 5), 'Index') == 0) {
  116. $model = ucfirst(substr($action, 0, -5));
  117. $parent = $this->loadModel($model)->get($event->getSubject()->args[0]);
  118. $this->set('parent', $parent);
  119. }
  120. }
  121. public function CrudAfterSave(Event $event)
  122. {
  123. $subject = $event->getSubject();
  124. if(!$subject->success)
  125. throw new ValidationException($subject->entity);
  126. if(!$subject->created) {
  127. $action = 'view';
  128. $oldAction = $this->request->getParam('action');
  129. if(strcmp(substr($oldAction, -4, 4), 'Edit') == 0) {
  130. $action = substr($oldAction, 0, -4) . 'View';
  131. }
  132. return $this->Crud->execute($action);
  133. }
  134. $location = $subject->entity->refresh()->getUrl();
  135. $this->response = $this->response->withStatus(201);
  136. $this->response = $this->response->withLocation($location);
  137. return $this->response;
  138. }
  139. public function CrudAfterDelete(Event $event)
  140. {
  141. $subject = $event->getSubject();
  142. if(!$subject->success)
  143. throw new ValidationException($subject->entity);
  144. $this->response = $this->response->withStatus(204);
  145. return $this->response;
  146. }
  147. public function CrudBeforeRedirect(Event $event)
  148. {
  149. if(method_exists($this->Crud->action(), 'publishViewVar'))
  150. $this->Crud->action()->publishViewVar($event);
  151. return $this->render();
  152. }
  153. protected function mapMethod($action, $auth = [], $contain = false)
  154. {
  155. $className = ucfirst($action);
  156. $className = preg_replace('/^.*([A-Z][a-z]+)$/', 'Crud.\\1', $className);
  157. if(is_string($auth))
  158. $auth = [$auth];
  159. if(empty($auth))
  160. $auth = ['super'];
  161. $config = compact('className','auth');
  162. if($contain)
  163. $config['findMethod'] = 'withContain';
  164. $this->Crud->mapAction($action, $config);
  165. }
  166. protected function setResponseModified()
  167. {
  168. $model = $this->modelClass;
  169. $query = $this->$model->find();
  170. $query->select(['last' => $query->func()->max("$model.modified")]);
  171. $modified = $this->doRawQuery($query);
  172. if($modified[0][0] == null) {
  173. $modified[0][0] = '1970-01-01 12:00:00';
  174. }
  175. $this->response = $this->response->withModified($modified[0][0]);
  176. return $this->response->checkNotModified($this->request);
  177. }
  178. protected function doRawQuery($query)
  179. {
  180. $q = trim($this->request->getQuery('q'));
  181. $orWhere = [];
  182. $params = [];
  183. $values = explode(' ', $q);
  184. foreach($this->searchFields as $field) {
  185. if(strlen($q) == 0)
  186. break;
  187. $andWhere = [];
  188. foreach($values as $val) {
  189. $andWhere[] = "$field LIKE ?";
  190. $params[] = "%$val%";
  191. }
  192. $orWhere[] = function($exp) use ($andWhere) {
  193. return $exp->and_($andWhere);
  194. };
  195. }
  196. if(!empty($orWhere)) {
  197. $query->andWhere(function($exp) use ($orWhere) {
  198. return $exp->or_($orWhere);
  199. });
  200. }
  201. $conn = ConnectionManager::get('default');
  202. return $conn->execute($query->sql(), $params)->fetchAll();
  203. }
  204. protected function doRawIndex($query, $class, $url, $id = 'id')
  205. {
  206. $content = [];
  207. foreach($this->doRawQuery($query) as $row) {
  208. $content[] =
  209. [ 'class' => $class
  210. , 'url' => $url . $row[0]
  211. , $id => (int)$row[0]
  212. , 'name' => $row[1]
  213. ];
  214. }
  215. $this->set('_serialize',
  216. [ 'class' => 'List'
  217. , 'url' => rtrim($this->request->getPath(), '/')
  218. , 'list' => $content
  219. ]);
  220. }
  221. protected function dataNameToId($table, $field)
  222. {
  223. $name = $this->request->getData($field);
  224. if(is_null($name)) {
  225. return null;
  226. }
  227. $this->request = $this->request->withoutData($field);
  228. if(empty($name)) {
  229. $name = "-";
  230. }
  231. $model = $this->loadModel($table);
  232. $ids = $model->findByName($name)->select('id', true)
  233. ->enableHydration(false)->all();
  234. if($ids->count() == 0) {
  235. $this->request = $this->request->withData($field.'_id', -1);
  236. } else {
  237. $this->request = $this->request->withData($field.'_id', $ids->first()['id']);
  238. }
  239. return $name;
  240. }
  241. protected function dataNameToIdAndAddIfMissing($table, $field)
  242. {
  243. $name = $this->dataNameToId($table, $field);
  244. $id = $this->request->getData($field.'_id');
  245. if($id < 0) {
  246. $model = $this->loadModel($table);
  247. $obj = $model->newEntity();
  248. $obj->name = $name;
  249. $model->save($obj);
  250. $this->request = $this->request->withData($field.'_id', $obj->id);
  251. }
  252. return $name;
  253. }
  254. }