PageRenderTime 36ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/_/app/Http/Controllers/CoreController.php

https://gitlab.com/billyprice1/MFAdmin
PHP | 419 lines | 386 code | 32 blank | 1 comment | 4 complexity | de9e40d26012e89764ee347a819a8285 MD5 | raw file
  1. <?php namespace App\Http\Controllers;
  2. use Illuminate\Foundation\Validation\ValidatesRequests;
  3. abstract class CoreController extends Controller
  4. {
  5. use ValidatesRequests;
  6. const SECTION_ALL = 'all';
  7. const SECTION_LAYOUT = 'layout';
  8. const SECTION_CONTENT = 'content';
  9. const SECTION_JS = 'js';
  10. const ASSET_CSS = 'css';
  11. const ASSET_JS = 'js';
  12. const LIBRARY_LOAD_PRIORITY_PRE = 'pre';
  13. const LIBRARY_LOAD_PRIORITY_POST = 'post';
  14. private $layout_view_filename;
  15. private $layout_view;
  16. protected $current_controller = [];
  17. protected $current_action = [];
  18. protected $current_page;
  19. protected $base_url;
  20. protected $ui;
  21. protected $is_ajax;
  22. protected $ajax;
  23. private $data =
  24. [
  25. self::SECTION_LAYOUT => [],
  26. self::SECTION_CONTENT => [],
  27. self::SECTION_JS => []
  28. ];
  29. private $assets =
  30. [
  31. self::ASSET_CSS => [],
  32. self::ASSET_JS => []
  33. ];
  34. private $libraries = [];
  35. private $loaded_libraries =
  36. [
  37. self::LIBRARY_LOAD_PRIORITY_PRE => [],
  38. self::LIBRARY_LOAD_PRIORITY_POST => []
  39. ];
  40. public function afterLayoutInit()
  41. {
  42. }
  43. protected function initLayout($method, $parameters)
  44. {
  45. if ( isset($this->layout) && $this->layout !== null )
  46. {
  47. $this->layout_view_filename = 'layouts/' . $this->layout;
  48. $this->layout_view = view($this->layout_view_filename);
  49. }
  50. $current_controller = $this->getController();
  51. $this->current_controller =
  52. [
  53. 'original' => $current_controller,
  54. 'underscore' => \App\Helpers\Core\Str::hyphenToUnderscore($current_controller)
  55. ];
  56. $this->current_action =
  57. [
  58. 'original' => $method,
  59. 'underscore' => \App\Helpers\Core\Str::camelCaseToUnderscore($method),
  60. 'hyphen' => \App\Helpers\Core\Str::camelCaseToHyphen($method)
  61. ];
  62. $this->current_page = $current_controller . '/' . $this->current_action['hyphen'];
  63. $this->base_url = \URL::route('home', [], FALSE);
  64. $this->assign('base_url', $this->base_url, [self::SECTION_LAYOUT, self::SECTION_JS]);
  65. $this->ui = new \App\Helpers\Core\UI();
  66. if ( $this->ui->haveMessage() )
  67. {
  68. $this->assign('core_message', $this->ui->getMessage(), 'js');
  69. $this->ui->deleteMessage();
  70. }
  71. $this->is_ajax = (\Request::ajax() === TRUE);
  72. $this->ajax = new \App\Helpers\Core\Ajax($this->ui);
  73. // CSRF
  74. $csrf_token = csrf_token();
  75. $this->assign('csrf_token', $csrf_token, self::SECTION_CONTENT);
  76. $encrypter = app('Illuminate\Encryption\Encrypter');
  77. $encrypted_csrf_token = $encrypter->encrypt($csrf_token);
  78. $this->assign('csrf_token', $csrf_token, self::SECTION_JS);
  79. $this->assign('encrypted_csrf_token', $encrypted_csrf_token, self::SECTION_JS);
  80. $this->afterLayoutInit();
  81. }
  82. protected function getController()
  83. {
  84. $controller = \Illuminate\Support\Str::parseCallback(\Route::currentRouteAction(), null)[0];
  85. if ( !preg_match('/^App\\\\Http\\\\Controllers\\\\([a-zA-Z\\\\]+)Controller$/', $controller, $controller_matches) )
  86. {
  87. throw new \Exception('Could not parse controller.');
  88. }
  89. return strtolower(str_replace('\\', '/', \App\Helpers\Core\Str::camelCaseToHyphen($controller_matches[1])));
  90. }
  91. public function assign($key, $value, $section = self::SECTION_CONTENT)
  92. {
  93. $assign = function($section, $key, $value)
  94. {
  95. if ( isset($this->data[$section][$key]) )
  96. {
  97. throw new \Exception('Key "' . $key . '" already assiged.');
  98. }
  99. $this->data[$section][$key] = $value;
  100. };
  101. if ( $section === self::SECTION_ALL )
  102. {
  103. $section = [self::SECTION_LAYOUT, self::SECTION_CONTENT, self::SECTION_JS];
  104. }
  105. if ( is_array($section) )
  106. {
  107. $sections = (array)$section;
  108. foreach ( $sections as $section )
  109. {
  110. $assign($section, $key, $value);
  111. }
  112. }
  113. else
  114. {
  115. $assign($section, $key, $value);
  116. }
  117. }
  118. protected function addLibrary($library_name, $css_files = NULL, $js_files = NULL)
  119. {
  120. $this->libraries[$library_name] =
  121. [
  122. self::ASSET_CSS => $css_files,
  123. self::ASSET_JS => $js_files
  124. ];
  125. }
  126. protected function loadCSS($path, $external = FALSE, $delayed = false)
  127. {
  128. foreach ( $this->assets[self::ASSET_CSS] as $css_file )
  129. {
  130. if ( $css_file['path'] === $path )
  131. {
  132. throw new \Exception('Stylesheet "' . $path . '" already added.');
  133. }
  134. }
  135. $this->assets[self::ASSET_CSS][] =
  136. [
  137. 'path' => $path,
  138. 'external' => $external,
  139. 'delayed' => $delayed
  140. ];
  141. }
  142. protected function loadJS($path, $external = false, $delayed = false)
  143. {
  144. if ( $delayed )
  145. {
  146. foreach ( $this->assets[self::ASSET_JS] as $js_file )
  147. {
  148. if ( $js_file['path'] === $path )
  149. {
  150. throw new \Exception('JavaScript "' . $path . '" already added.');
  151. }
  152. }
  153. }
  154. $this->assets[self::ASSET_JS][] =
  155. [
  156. 'path' => $path,
  157. 'external' => $external,
  158. 'delayed' => $delayed
  159. ];
  160. }
  161. protected function loadLibrary($library_name, $load_priority = self::LIBRARY_LOAD_PRIORITY_PRE)
  162. {
  163. if ( !isset($this->libraries[$library_name]) )
  164. {
  165. throw new \Exception('Library "' . $library_name . '" does not exist.');
  166. }
  167. $this->loaded_libraries[$load_priority][] = $library_name;
  168. }
  169. private function includeCSS($css)
  170. {
  171. if ( is_array($css) )
  172. {
  173. foreach ( $css as $css_file )
  174. {
  175. $this->loadCSS($css_file);
  176. }
  177. }
  178. else
  179. {
  180. $this->loadCSS($css);
  181. }
  182. }
  183. private function includeJS($js)
  184. {
  185. if ( is_array($js) )
  186. {
  187. foreach ( $js as $js_file )
  188. {
  189. $this->loadJS($js_file);
  190. }
  191. }
  192. else
  193. {
  194. $this->loadJS($js);
  195. }
  196. }
  197. private function includeLibrary($library_name)
  198. {
  199. if ( !isset($this->libraries[$library_name]) )
  200. {
  201. throw new \Exception('Could not find library "' . $library_name . '".');
  202. }
  203. $library = $this->libraries[$library_name];
  204. if ( isset($library[self::ASSET_CSS]) )
  205. {
  206. $this->includeCSS($library[self::ASSET_CSS]);
  207. }
  208. if ( isset($library[self::ASSET_JS]) )
  209. {
  210. $this->includeJS($library[self::ASSET_JS]);
  211. }
  212. }
  213. private function includeAssets($libraries, array $css_files, array $js_files)
  214. {
  215. // Pre-loaded libraries
  216. foreach ( $this->loaded_libraries[self::LIBRARY_LOAD_PRIORITY_PRE] as $lib_name )
  217. {
  218. $this->includeLibrary($lib_name);
  219. }
  220. // Libraries loaded from display() function
  221. foreach ( $libraries as $lib_name )
  222. {
  223. $this->includeLibrary($lib_name);
  224. }
  225. // Post-loaded libraries
  226. foreach ( $this->loaded_libraries[self::LIBRARY_LOAD_PRIORITY_POST] as $lib_name )
  227. {
  228. $this->includeLibrary($lib_name);
  229. }
  230. // Auto load layout CSS & JS
  231. $css_layout_filename = 'css/' . str_replace('.', '/', $this->layout_view->getName()) . '.css';
  232. $css_layout_path = public_path() . '/' . $css_layout_filename;
  233. if ( file_exists($css_layout_path) )
  234. {
  235. $this->loadCSS($css_layout_filename);
  236. }
  237. $js_layout_filename = 'js/' . str_replace('.', '/', $this->layout_view->getName()) . '.js';
  238. $js_layout_path = public_path() . '/' . $js_layout_filename;
  239. if ( file_exists($js_layout_path) )
  240. {
  241. $this->loadJS($js_layout_filename);
  242. }
  243. // Automatically load CSS & JS based off route
  244. $css_short_auto_path = 'css/' . $this->current_controller['underscore'] . '/' . $this->current_action['underscore'] . '.css';
  245. $css_auto_path = public_path() . '/' . $css_short_auto_path;
  246. if ( file_exists($css_auto_path) )
  247. {
  248. $this->includeCSS($css_short_auto_path);
  249. }
  250. $js_short_auto_path = 'js/' . $this->current_controller['underscore'] . '/' . $this->current_action['underscore'] . '.js';
  251. $js_auto_path = public_path() . '/' . $js_short_auto_path;
  252. if ( file_exists($js_auto_path) )
  253. {
  254. $this->includeJS($js_short_auto_path);
  255. }
  256. // CSS loaded from display() function
  257. foreach ( $css_files as $css_file )
  258. {
  259. $this->includeCSS($css_file);
  260. }
  261. // JS loaded from display() function
  262. foreach ( $js_files as $js_file )
  263. {
  264. $this->includeJS($js_file);
  265. }
  266. }
  267. private function includeContentData()
  268. {
  269. $this->assign('current_page', $this->current_page, self::SECTION_ALL);
  270. $this->assign('page_id', $this->current_controller['underscore'] . '_' . $this->current_action['underscore'] . '_page', self::SECTION_LAYOUT);
  271. foreach ( $this->data[self::SECTION_LAYOUT] as $key => $value )
  272. {
  273. $this->layout_view->$key = $value;
  274. }
  275. $this->layout_view->assets = $this->assets;
  276. }
  277. private function getContentData()
  278. {
  279. return array_merge
  280. (
  281. $this->data[self::SECTION_CONTENT],
  282. ['js_vars' => $this->data[self::SECTION_JS]]
  283. );
  284. }
  285. private function generatePageTitle($page_title, $page_title_suffix)
  286. {
  287. if ( $page_title !== NULL )
  288. {
  289. return ((is_array($page_title) ? implode(' | ', $page_title) : $page_title) . ($page_title_suffix ? ' ' . \Config::get('custom.PAGE_TITLE_SEPARATOR') . ' ' . \Config::get('custom.PAGE_TITLE_SUFFIX') : ''));
  290. }
  291. else
  292. {
  293. return \Config::get('custom.DEFAULT_PAGE_TITLE');
  294. }
  295. }
  296. private function includejQuery()
  297. {
  298. $jquery_view = view('layouts/partials/jquery');
  299. $jquery_view->base_url = $this->base_url;
  300. $this->layout_view->jquery = $jquery_view->render();
  301. }
  302. private function includeInlineJS()
  303. {
  304. $inline_js_view = view('layouts/partials/inline_js');
  305. $inline_js_view->js_variables = $this->data[self::ASSET_JS];
  306. $this->layout_view->inline_js = $inline_js_view->render();
  307. }
  308. public function beforeDisplay()
  309. {
  310. }
  311. public function display($page_title = NULL, $page_title_suffix = TRUE, array $libraries = [], array $css_files = [], array $js_files = [], $view_file = NULL)
  312. {
  313. $this->beforeDisplay();
  314. $this->layout_view->page_title = ($page_title !== NULL ? $this->generatePageTitle($page_title, $page_title_suffix) : \Config::get('custom.DEFAULT_PAGE_TITLE'));
  315. $this->includeAssets($libraries, $css_files, $js_files);
  316. $this->includeContentData();
  317. $this->includejQuery();
  318. $this->includeInlineJS();
  319. if ( $view_file === NULL )
  320. {
  321. $view_file = $this->current_controller['underscore'] . '/' . $this->current_action['underscore'];
  322. }
  323. return $this->layout_view->nest
  324. (
  325. 'content',
  326. $view_file,
  327. $this->getContentData()
  328. );
  329. }
  330. public function getCurrentController()
  331. {
  332. return $this->current_controller['original'];
  333. }
  334. public function getCurrentAction()
  335. {
  336. return $this->current_action['original'];
  337. }
  338. }