ItemController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Application;
  4. use App\Item;
  5. use App\Jobs\ProcessApps;
  6. use App\Search;
  7. use App\Setting;
  8. use App\SupportedApps;
  9. use App\User;
  10. use Artisan;
  11. use GrahamCampbell\GitHub\Facades\GitHub;
  12. use GuzzleHttp\Client;
  13. use GuzzleHttp\Exception\GuzzleException;
  14. use Illuminate\Http\Request;
  15. use Illuminate\Support\Facades\Log;
  16. use Illuminate\Support\Facades\Route;
  17. use Illuminate\Support\Facades\Storage;
  18. use Illuminate\Support\Facades\URL;
  19. class ItemController extends Controller
  20. {
  21. public function __construct()
  22. {
  23. $this->middleware('allowed');
  24. }
  25. /**
  26. * Display a listing of the resource on the dashboard.
  27. *
  28. * @return \Illuminate\Http\Response
  29. */
  30. public function dash()
  31. {
  32. $data['apps'] = Item::whereHas('parents', function ($query) {
  33. $query->where('id', 0);
  34. })->orWhere('type', 1)->pinned()->orderBy('order', 'asc')->get();
  35. $data['all_apps'] = Item::whereHas('parents', function ($query) {
  36. $query->where('id', 0);
  37. })->orWhere('type', 1)->orderBy('order', 'asc')->get();
  38. //$data['all_apps'] = Item::doesntHave('parents')->get();
  39. //die(print_r($data['apps']));
  40. return view('welcome', $data);
  41. }
  42. /**
  43. * Set order on the dashboard.
  44. *
  45. * @return \Illuminate\Http\Response
  46. */
  47. public function setOrder(Request $request)
  48. {
  49. $order = array_filter($request->input('order'));
  50. foreach ($order as $o => $id) {
  51. $item = Item::find($id);
  52. $item->order = $o;
  53. $item->save();
  54. }
  55. }
  56. /**
  57. * Pin item on the dashboard.
  58. *
  59. * @return \Illuminate\Http\Response
  60. */
  61. public function pin($id)
  62. {
  63. $item = Item::findOrFail($id);
  64. $item->pinned = true;
  65. $item->save();
  66. $route = route('dash', []);
  67. return redirect($route);
  68. }
  69. /**
  70. * Unpin item on the dashboard.
  71. *
  72. * @return \Illuminate\Http\Response
  73. */
  74. public function unpin($id)
  75. {
  76. $item = Item::findOrFail($id);
  77. $item->pinned = false;
  78. $item->save();
  79. $route = route('dash', []);
  80. return redirect($route);
  81. }
  82. /**
  83. * Unpin item on the dashboard.
  84. *
  85. * @return \Illuminate\Http\Response
  86. */
  87. public function pinToggle($id, $ajax = false, $tag = false)
  88. {
  89. $item = Item::findOrFail($id);
  90. $new = ((bool) $item->pinned === true) ? false : true;
  91. $item->pinned = $new;
  92. $item->save();
  93. if ($ajax) {
  94. if (is_numeric($tag) && $tag > 0) {
  95. $item = Item::whereId($tag)->first();
  96. $data['apps'] = $item->children()->pinned()->orderBy('order', 'asc')->get();
  97. } else {
  98. $data['apps'] = Item::pinned()->orderBy('order', 'asc')->get();
  99. }
  100. $data['ajax'] = true;
  101. return view('sortable', $data);
  102. } else {
  103. $route = route('dash', []);
  104. return redirect($route);
  105. }
  106. }
  107. /**
  108. * Display a listing of the resource.
  109. *
  110. * @return \Illuminate\Http\Response
  111. */
  112. public function index(Request $request)
  113. {
  114. $trash = (bool) $request->input('trash');
  115. $data['apps'] = Item::ofType('item')->orderBy('title', 'asc')->get();
  116. $data['trash'] = Item::ofType('item')->onlyTrashed()->get();
  117. if ($trash) {
  118. return view('items.trash', $data);
  119. } else {
  120. return view('items.list', $data);
  121. }
  122. }
  123. /**
  124. * Show the form for creating a new resource.
  125. *
  126. * @return \Illuminate\Http\Response
  127. */
  128. public function create()
  129. {
  130. //
  131. $data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
  132. $data['tags']->prepend(__('app.dashboard'), 0);
  133. $data['current_tags'] = '0';
  134. return view('items.create', $data);
  135. }
  136. /**
  137. * Show the form for editing the specified resource.
  138. *
  139. * @param int $id
  140. * @return \Illuminate\Http\Response
  141. */
  142. public function edit($id)
  143. {
  144. // Get the item
  145. $item = Item::find($id);
  146. if ($item->appid === null && $item->class !== null) { // old apps wont have an app id so set it
  147. $app = Application::where('class', $item->class)->first();
  148. if ($app) {
  149. $item->appid = $app->appid;
  150. }
  151. }
  152. $data['item'] = $item;
  153. $data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
  154. $data['tags']->prepend(__('app.dashboard'), 0);
  155. $data['current_tags'] = $data['item']->tags();
  156. //$data['current_tags'] = $data['item']->parent;
  157. //die(print_r($data['current_tags']));
  158. // show the edit form and pass the nerd
  159. return view('items.edit', $data);
  160. }
  161. public function storelogic($request, $id = null)
  162. {
  163. $application = Application::single($request->input('appid'));
  164. $validatedData = $request->validate([
  165. 'title' => 'required|max:255',
  166. 'url' => 'required',
  167. ]);
  168. if ($request->hasFile('file')) {
  169. $path = $request->file('file')->store('icons');
  170. $request->merge([
  171. 'icon' => $path,
  172. ]);
  173. } elseif (strpos($request->input('icon'), 'http') === 0) {
  174. $options=array(
  175. "ssl"=>array(
  176. "verify_peer"=>false,
  177. "verify_peer_name"=>false,
  178. ),
  179. );
  180. $contents = file_get_contents($request->input('icon'), false, stream_context_create($options));
  181. if ($application) {
  182. $icon = $application->icon;
  183. } else {
  184. $file = $request->input('icon');
  185. $path_parts = pathinfo($file);
  186. $icon = md5($contents);
  187. $icon .= '.'.$path_parts['extension'];
  188. }
  189. $path = 'icons/'.$icon;
  190. // Private apps could have here duplicated icons folder
  191. if (strpos($path, 'icons/icons/') !== false) {
  192. $path = str_replace('icons/icons/','icons/',$path);
  193. }
  194. Storage::disk('public')->put($path, $contents);
  195. $request->merge([
  196. 'icon' => $path,
  197. ]);
  198. }
  199. $config = Item::checkConfig($request->input('config'));
  200. $current_user = User::currentUser();
  201. $request->merge([
  202. 'description' => $config,
  203. 'user_id' => $current_user->id,
  204. ]);
  205. if ($request->input('appid') === 'null') {
  206. $request->merge([
  207. 'class' => null,
  208. ]);
  209. } else {
  210. $request->merge([
  211. 'class' => Application::classFromName($application->name),
  212. ]);
  213. }
  214. if ($id === null) {
  215. $item = Item::create($request->all());
  216. } else {
  217. $item = Item::find($id);
  218. $item->update($request->all());
  219. }
  220. $item->parents()->sync($request->tags);
  221. }
  222. /**
  223. * Store a newly created resource in storage.
  224. *
  225. * @param \Illuminate\Http\Request $request
  226. * @return \Illuminate\Http\Response
  227. */
  228. public function store(Request $request)
  229. {
  230. $this->storelogic($request);
  231. $route = route('dash', []);
  232. return redirect($route)
  233. ->with('success', __('app.alert.success.item_created'));
  234. }
  235. /**
  236. * Display the specified resource.
  237. *
  238. * @param int $id
  239. * @return \Illuminate\Http\Response
  240. */
  241. public function show($id)
  242. {
  243. //
  244. }
  245. /**
  246. * Update the specified resource in storage.
  247. *
  248. * @param \Illuminate\Http\Request $request
  249. * @param int $id
  250. * @return \Illuminate\Http\Response
  251. */
  252. public function update(Request $request, $id)
  253. {
  254. $this->storelogic($request, $id);
  255. $route = route('dash', []);
  256. return redirect($route)
  257. ->with('success', __('app.alert.success.item_updated'));
  258. }
  259. /**
  260. * Remove the specified resource from storage.
  261. *
  262. * @param int $id
  263. * @return \Illuminate\Http\Response
  264. */
  265. public function destroy(Request $request, $id)
  266. {
  267. //
  268. $force = (bool) $request->input('force');
  269. if ($force) {
  270. Item::withTrashed()
  271. ->where('id', $id)
  272. ->forceDelete();
  273. } else {
  274. Item::find($id)->delete();
  275. }
  276. $route = route('items.index', []);
  277. return redirect($route)
  278. ->with('success', __('app.alert.success.item_deleted'));
  279. }
  280. /**
  281. * Restore the specified resource from soft deletion.
  282. *
  283. * @param int $id
  284. * @return \Illuminate\Http\Response
  285. */
  286. public function restore($id)
  287. {
  288. //
  289. Item::withTrashed()
  290. ->where('id', $id)
  291. ->restore();
  292. $route = route('items.index', []);
  293. return redirect($route)
  294. ->with('success', __('app.alert.success.item_restored'));
  295. }
  296. /**
  297. * Return details for supported apps
  298. *
  299. * @return Json
  300. */
  301. public function appload(Request $request)
  302. {
  303. $output = [];
  304. $appid = $request->input('app');
  305. if ($appid === 'null') {
  306. return null;
  307. }
  308. /*$appname = $request->input('app');
  309. //die($appname);
  310. $app_details = Application::where('name', $appname)->firstOrFail();
  311. $appclass = $app_details->class();
  312. $app = new $appclass;
  313. // basic details
  314. $output['icon'] = $app_details->icon();
  315. $output['name'] = $app_details->name;
  316. $output['iconview'] = $app_details->iconView();
  317. $output['colour'] = $app_details->defaultColour();
  318. $output['class'] = $appclass;
  319. // live details
  320. if($app instanceof \App\EnhancedApps) {
  321. $output['config'] = className($app_details->name).'.config';
  322. } else {
  323. $output['config'] = null;
  324. }*/
  325. $output['config'] = null;
  326. $output['custom'] = null;
  327. $app = Application::single($appid);
  328. $output = (array) $app;
  329. $appdetails = Application::getApp($appid);
  330. if ((bool) $app->enhanced === true) {
  331. // if(!isset($app->config)) { // class based config
  332. $output['custom'] = className($appdetails->name).'.config';
  333. // }
  334. }
  335. $output['colour'] = ($app->tile_background == 'light') ? '#fafbfc' : '#161b1f';
  336. if(strpos($app->icon, '://') !== false) {
  337. $output['iconview'] = $app->icon;
  338. } elseif(strpos($app->icon, 'icons/') !== false) {
  339. // Private apps have the icon locally
  340. $output['iconview'] = URL::to('/').'/storage/'.$app->icon;
  341. $output['icon'] = str_replace('icons/', '', $output['icon']);
  342. } else {
  343. $output['iconview'] = config('app.appsource').'icons/'.$app->icon;
  344. }
  345. return json_encode($output);
  346. }
  347. public function testConfig(Request $request)
  348. {
  349. $data = $request->input('data');
  350. //$url = $data[array_search('url', array_column($data, 'name'))]['value'];
  351. $single = Application::single($data['type']);
  352. $app = $single->class;
  353. $app_details = new $app();
  354. $app_details->config = (object) $data;
  355. $app_details->test();
  356. }
  357. public function execute($url, $attrs = [], $overridevars = false)
  358. {
  359. $res = null;
  360. $vars = ($overridevars !== false) ?
  361. $overridevars : [
  362. 'http_errors' => false,
  363. 'timeout' => 15,
  364. 'connect_timeout' => 15,
  365. 'verify' => false,
  366. ];
  367. $client = new Client($vars);
  368. $method = 'GET';
  369. try {
  370. return $client->request($method, $url, $attrs);
  371. } catch (\GuzzleHttp\Exception\ConnectException $e) {
  372. Log::error('Connection refused');
  373. Log::debug($e->getMessage());
  374. } catch (\GuzzleHttp\Exception\ServerException $e) {
  375. Log::debug($e->getMessage());
  376. }
  377. return $res;
  378. }
  379. public function websitelookup($url)
  380. {
  381. $url = \base64_decode($url);
  382. $data = $this->execute($url);
  383. return $data->getBody();
  384. }
  385. public function getStats($id)
  386. {
  387. $item = Item::find($id);
  388. $config = $item->getconfig();
  389. if (isset($item->class)) {
  390. $application = new $item->class;
  391. $application->config = $config;
  392. echo $application->livestats();
  393. }
  394. }
  395. public function checkAppList()
  396. {
  397. ProcessApps::dispatch();
  398. $route = route('items.index');
  399. return redirect($route)
  400. ->with('success', __('app.alert.success.updating'));
  401. }
  402. }