summaryrefslogtreecommitdiff
path: root/ssh/app
diff options
context:
space:
mode:
Diffstat (limited to 'ssh/app')
-rw-r--r--ssh/app/Article.php23
-rw-r--r--ssh/app/Category.php18
-rw-r--r--ssh/app/Console/Commands/GenerateSitemap.php52
-rw-r--r--ssh/app/Console/Kernel.php41
-rw-r--r--ssh/app/Discussion.php24
-rw-r--r--ssh/app/Exceptions/Handler.php55
-rw-r--r--ssh/app/Http/Controllers/Auth/ConfirmPasswordController.php40
-rw-r--r--ssh/app/Http/Controllers/Auth/ForgotPasswordController.php22
-rw-r--r--ssh/app/Http/Controllers/Auth/LoginController.php40
-rw-r--r--ssh/app/Http/Controllers/Auth/RegisterController.php73
-rw-r--r--ssh/app/Http/Controllers/Auth/ResetPasswordController.php30
-rw-r--r--ssh/app/Http/Controllers/Auth/VerificationController.php42
-rw-r--r--ssh/app/Http/Controllers/CinemaController.php233
-rw-r--r--ssh/app/Http/Controllers/Controller.php13
-rw-r--r--ssh/app/Http/Controllers/FeedController.php97
-rw-r--r--ssh/app/Http/Controllers/HomeController.php28
-rw-r--r--ssh/app/Http/Controllers/IndexController.php150
-rw-r--r--ssh/app/Http/Kernel.php66
-rw-r--r--ssh/app/Http/Middleware/Authenticate.php21
-rw-r--r--ssh/app/Http/Middleware/CheckForMaintenanceMode.php17
-rw-r--r--ssh/app/Http/Middleware/EncryptCookies.php17
-rw-r--r--ssh/app/Http/Middleware/RedirectIfAuthenticated.php27
-rw-r--r--ssh/app/Http/Middleware/TrimStrings.php18
-rw-r--r--ssh/app/Http/Middleware/TrustProxies.php29
-rw-r--r--ssh/app/Http/Middleware/VerifyCsrfToken.php17
-rw-r--r--ssh/app/Libraries/Helper.php303
-rw-r--r--ssh/app/Providers/AppServiceProvider.php29
-rw-r--r--ssh/app/Providers/AuthServiceProvider.php30
-rw-r--r--ssh/app/Providers/BroadcastServiceProvider.php21
-rw-r--r--ssh/app/Providers/EventServiceProvider.php34
-rw-r--r--ssh/app/Providers/RouteServiceProvider.php80
-rw-r--r--ssh/app/User.php39
32 files changed, 1729 insertions, 0 deletions
diff --git a/ssh/app/Article.php b/ssh/app/Article.php
new file mode 100644
index 0000000..9f11ea3
--- /dev/null
+++ b/ssh/app/Article.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Article extends Model
+{
+ protected $table = "view_article";
+
+ protected $fillable = [
+ ];
+
+ public function getDiscussions() {
+ #return $this->hasMany('App\Discussion', 'article_id', 'id');
+ return $this->hasMany('App\Discussion');
+ }
+
+ public function getCategories() {
+ return $this->belongsToMany('App\Category', 'article_category');
+ }
+}
+
diff --git a/ssh/app/Category.php b/ssh/app/Category.php
new file mode 100644
index 0000000..7f0cdb2
--- /dev/null
+++ b/ssh/app/Category.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Category extends Model
+{
+ protected $table = "category";
+ protected $fillable = [
+ 'id',
+ 'name'
+ ];
+
+ public function getArticles(){
+ return $this->belongsToMany('App\Article', 'article_category');
+ }
+}
diff --git a/ssh/app/Console/Commands/GenerateSitemap.php b/ssh/app/Console/Commands/GenerateSitemap.php
new file mode 100644
index 0000000..46bb0ac
--- /dev/null
+++ b/ssh/app/Console/Commands/GenerateSitemap.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use Spatie\Sitemap\SitemapGenerator;
+use Psr\Http\Message\UriInterface;
+
+class GenerateSitemap extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'sitemap:generate';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Generate the sitemap';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ // modify this to your own needs
+ SitemapGenerator::create(config('app.url'))
+ ->shouldCrawl(function (UriInterface $url) {
+ /**
+ * Prevent the crawler from crawling the random pages.
+ */
+ return strpos($url->getPath(), '/random') === false;
+ })
+ ->writeToFile(public_path('sitemap.xml'));
+ }
+}
diff --git a/ssh/app/Console/Kernel.php b/ssh/app/Console/Kernel.php
new file mode 100644
index 0000000..69914e9
--- /dev/null
+++ b/ssh/app/Console/Kernel.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Console;
+
+use Illuminate\Console\Scheduling\Schedule;
+use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
+
+class Kernel extends ConsoleKernel
+{
+ /**
+ * The Artisan commands provided by your application.
+ *
+ * @var array
+ */
+ protected $commands = [
+ //
+ ];
+
+ /**
+ * Define the application's command schedule.
+ *
+ * @param \Illuminate\Console\Scheduling\Schedule $schedule
+ * @return void
+ */
+ protected function schedule(Schedule $schedule)
+ {
+ // $schedule->command('inspire')->hourly();
+ }
+
+ /**
+ * Register the commands for the application.
+ *
+ * @return void
+ */
+ protected function commands()
+ {
+ $this->load(__DIR__.'/Commands');
+
+ require base_path('routes/console.php');
+ }
+}
diff --git a/ssh/app/Discussion.php b/ssh/app/Discussion.php
new file mode 100644
index 0000000..facb847
--- /dev/null
+++ b/ssh/app/Discussion.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Discussion extends Model
+{
+ protected $table = "discussion";
+ protected $fillable = [
+ 'article_id',
+ 'title',
+ 'source',
+ 'item_id',
+ 'source_url',
+ 'posted_on',
+ 'comments',
+ 'upvotes'
+ ];
+
+ public function getArticle() {
+ $this->belongsTo('App\Article');
+ }
+}
diff --git a/ssh/app/Exceptions/Handler.php b/ssh/app/Exceptions/Handler.php
new file mode 100644
index 0000000..59c585d
--- /dev/null
+++ b/ssh/app/Exceptions/Handler.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Exceptions;
+
+use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
+use Throwable;
+
+class Handler extends ExceptionHandler
+{
+ /**
+ * A list of the exception types that are not reported.
+ *
+ * @var array
+ */
+ protected $dontReport = [
+ //
+ ];
+
+ /**
+ * A list of the inputs that are never flashed for validation exceptions.
+ *
+ * @var array
+ */
+ protected $dontFlash = [
+ 'password',
+ 'password_confirmation',
+ ];
+
+ /**
+ * Report or log an exception.
+ *
+ * @param \Throwable $exception
+ * @return void
+ *
+ * @throws \Exception
+ */
+ public function report(Throwable $exception)
+ {
+ parent::report($exception);
+ }
+
+ /**
+ * Render an exception into an HTTP response.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @param \Throwable $exception
+ * @return \Symfony\Component\HttpFoundation\Response
+ *
+ * @throws \Throwable
+ */
+ public function render($request, Throwable $exception)
+ {
+ return parent::render($request, $exception);
+ }
+}
diff --git a/ssh/app/Http/Controllers/Auth/ConfirmPasswordController.php b/ssh/app/Http/Controllers/Auth/ConfirmPasswordController.php
new file mode 100644
index 0000000..138c1f0
--- /dev/null
+++ b/ssh/app/Http/Controllers/Auth/ConfirmPasswordController.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Http\Controllers\Auth;
+
+use App\Http\Controllers\Controller;
+use App\Providers\RouteServiceProvider;
+use Illuminate\Foundation\Auth\ConfirmsPasswords;
+
+class ConfirmPasswordController extends Controller
+{
+ /*
+ |--------------------------------------------------------------------------
+ | Confirm Password Controller
+ |--------------------------------------------------------------------------
+ |
+ | This controller is responsible for handling password confirmations and
+ | uses a simple trait to include the behavior. You're free to explore
+ | this trait and override any functions that require customization.
+ |
+ */
+
+ use ConfirmsPasswords;
+
+ /**
+ * Where to redirect users when the intended url fails.
+ *
+ * @var string
+ */
+ protected $redirectTo = RouteServiceProvider::HOME;
+
+ /**
+ * Create a new controller instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->middleware('auth');
+ }
+}
diff --git a/ssh/app/Http/Controllers/Auth/ForgotPasswordController.php b/ssh/app/Http/Controllers/Auth/ForgotPasswordController.php
new file mode 100644
index 0000000..465c39c
--- /dev/null
+++ b/ssh/app/Http/Controllers/Auth/ForgotPasswordController.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Http\Controllers\Auth;
+
+use App\Http\Controllers\Controller;
+use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
+
+class ForgotPasswordController extends Controller
+{
+ /*
+ |--------------------------------------------------------------------------
+ | Password Reset Controller
+ |--------------------------------------------------------------------------
+ |
+ | This controller is responsible for handling password reset emails and
+ | includes a trait which assists in sending these notifications from
+ | your application to your users. Feel free to explore this trait.
+ |
+ */
+
+ use SendsPasswordResetEmails;
+}
diff --git a/ssh/app/Http/Controllers/Auth/LoginController.php b/ssh/app/Http/Controllers/Auth/LoginController.php
new file mode 100644
index 0000000..18a0d08
--- /dev/null
+++ b/ssh/app/Http/Controllers/Auth/LoginController.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Http\Controllers\Auth;
+
+use App\Http\Controllers\Controller;
+use App\Providers\RouteServiceProvider;
+use Illuminate\Foundation\Auth\AuthenticatesUsers;
+
+class LoginController extends Controller
+{
+ /*
+ |--------------------------------------------------------------------------
+ | Login Controller
+ |--------------------------------------------------------------------------
+ |
+ | This controller handles authenticating users for the application and
+ | redirecting them to your home screen. The controller uses a trait
+ | to conveniently provide its functionality to your applications.
+ |
+ */
+
+ use AuthenticatesUsers;
+
+ /**
+ * Where to redirect users after login.
+ *
+ * @var string
+ */
+ protected $redirectTo = RouteServiceProvider::HOME;
+
+ /**
+ * Create a new controller instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->middleware('guest')->except('logout');
+ }
+}
diff --git a/ssh/app/Http/Controllers/Auth/RegisterController.php b/ssh/app/Http/Controllers/Auth/RegisterController.php
new file mode 100644
index 0000000..c6a6de6
--- /dev/null
+++ b/ssh/app/Http/Controllers/Auth/RegisterController.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace App\Http\Controllers\Auth;
+
+use App\Http\Controllers\Controller;
+use App\Providers\RouteServiceProvider;
+use App\User;
+use Illuminate\Foundation\Auth\RegistersUsers;
+use Illuminate\Support\Facades\Hash;
+use Illuminate\Support\Facades\Validator;
+
+class RegisterController extends Controller
+{
+ /*
+ |--------------------------------------------------------------------------
+ | Register Controller
+ |--------------------------------------------------------------------------
+ |
+ | This controller handles the registration of new users as well as their
+ | validation and creation. By default this controller uses a trait to
+ | provide this functionality without requiring any additional code.
+ |
+ */
+
+ use RegistersUsers;
+
+ /**
+ * Where to redirect users after registration.
+ *
+ * @var string
+ */
+ protected $redirectTo = RouteServiceProvider::HOME;
+
+ /**
+ * Create a new controller instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->middleware('guest');
+ }
+
+ /**
+ * Get a validator for an incoming registration request.
+ *
+ * @param array $data
+ * @return \Illuminate\Contracts\Validation\Validator
+ */
+ protected function validator(array $data)
+ {
+ return Validator::make($data, [
+ 'name' => ['required', 'string', 'max:255'],
+ 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
+ 'password' => ['required', 'string', 'min:8', 'confirmed'],
+ ]);
+ }
+
+ /**
+ * Create a new user instance after a valid registration.
+ *
+ * @param array $data
+ * @return \App\User
+ */
+ protected function create(array $data)
+ {
+ return User::create([
+ 'name' => $data['name'],
+ 'email' => $data['email'],
+ 'password' => Hash::make($data['password']),
+ ]);
+ }
+}
diff --git a/ssh/app/Http/Controllers/Auth/ResetPasswordController.php b/ssh/app/Http/Controllers/Auth/ResetPasswordController.php
new file mode 100644
index 0000000..b1726a3
--- /dev/null
+++ b/ssh/app/Http/Controllers/Auth/ResetPasswordController.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Http\Controllers\Auth;
+
+use App\Http\Controllers\Controller;
+use App\Providers\RouteServiceProvider;
+use Illuminate\Foundation\Auth\ResetsPasswords;
+
+class ResetPasswordController extends Controller
+{
+ /*
+ |--------------------------------------------------------------------------
+ | Password Reset Controller
+ |--------------------------------------------------------------------------
+ |
+ | This controller is responsible for handling password reset requests
+ | and uses a simple trait to include this behavior. You're free to
+ | explore this trait and override any methods you wish to tweak.
+ |
+ */
+
+ use ResetsPasswords;
+
+ /**
+ * Where to redirect users after resetting their password.
+ *
+ * @var string
+ */
+ protected $redirectTo = RouteServiceProvider::HOME;
+}
diff --git a/ssh/app/Http/Controllers/Auth/VerificationController.php b/ssh/app/Http/Controllers/Auth/VerificationController.php
new file mode 100644
index 0000000..5e749af
--- /dev/null
+++ b/ssh/app/Http/Controllers/Auth/VerificationController.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace App\Http\Controllers\Auth;
+
+use App\Http\Controllers\Controller;
+use App\Providers\RouteServiceProvider;
+use Illuminate\Foundation\Auth\VerifiesEmails;
+
+class VerificationController extends Controller
+{
+ /*
+ |--------------------------------------------------------------------------
+ | Email Verification Controller
+ |--------------------------------------------------------------------------
+ |
+ | This controller is responsible for handling email verification for any
+ | user that recently registered with the application. Emails may also
+ | be re-sent if the user didn't receive the original email message.
+ |
+ */
+
+ use VerifiesEmails;
+
+ /**
+ * Where to redirect users after verification.
+ *
+ * @var string
+ */
+ protected $redirectTo = RouteServiceProvider::HOME;
+
+ /**
+ * Create a new controller instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->middleware('auth');
+ $this->middleware('signed')->only('verify');
+ $this->middleware('throttle:6,1')->only('verify', 'resend');
+ }
+}
diff --git a/ssh/app/Http/Controllers/CinemaController.php b/ssh/app/Http/Controllers/CinemaController.php
new file mode 100644
index 0000000..75c93aa
--- /dev/null
+++ b/ssh/app/Http/Controllers/CinemaController.php
@@ -0,0 +1,233 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Support\Facades\DB;
+use Illuminate\Http\Request;
+
+class CinemaController extends Controller
+{
+ public function cinema(Request $request)
+ {
+ $order = $request->input('order', 'ref_count');
+ $direction = $request->input('direction', 'desc');
+ $validOrders = ['ref_count', 'score', 'num_votes', 'num_accolades', 'start_year'];
+ $validDirections = ['asc', 'desc'];
+ if (! in_array($order, $validOrders)) {
+ $order = 'ref_count';
+ }
+ if (! in_array($direction, $validDirections)) {
+ $direction = 'desc';
+ }
+
+ $refCounts = DB::connection('cinema')
+ ->table('links')
+ ->select('links.param', DB::raw('COUNT(*) as ref_count'))
+ ->where('links.host', 'www.imdb.com')
+ ->where('links.field', 1)
+ ->groupBy('links.param');
+
+ $movies = DB::connection('cinema')
+ ->table('imdb')
+ ->select(
+ 'imdb.id',
+ 'imdb.imdb_id',
+ 'imdb.primary_title',
+ 'imdb.original_title',
+ 'imdb.start_year',
+ 'imdb.average_rating',
+ 'imdb.num_votes',
+ 'imdb.synopsis',
+ 'imdb.poster_url',
+ 'imdb.title_type',
+ 'imdb.runtime_minutes',
+ 'imdb.has_people',
+ 'imdb.average_rating as score',
+ 'imdb.num_accolades',
+ DB::raw('COALESCE(ref.ref_count, 0) as ref_count')
+ )
+ ->leftJoinSub($refCounts, 'ref', function ($join) {
+ $join->on('ref.param', '=', 'imdb.imdb_id');
+ })
+ ->whereNotNull('imdb.primary_title')
+ ->whereNotNull('imdb.wiki_article')
+ ->where('imdb.title_type', 'movie')
+ ->orderBy($order, $direction)
+ ->simplePaginate(12);
+
+ $total = DB::connection('cinema')
+ ->table('imdb')
+ ->whereNotNull('primary_title')
+ ->whereNotNull('wiki_article')
+ ->where('title_type', 'movie')
+ ->count();
+
+ return view('cinema', ['movies' => $movies, 'count' => $total, 'order' => $order, 'direction' => $direction]);
+ }
+
+ public function show($id)
+ {
+ $movie = DB::connection('cinema')
+ ->table('imdb')
+ ->where('imdb.imdb_id', $id)
+ ->first();
+
+ if (! $movie) {
+ abort(404);
+ }
+
+ $genres = DB::connection('cinema')
+ ->table('imdb_genre')
+ ->join('genre', 'genre.id', '=', 'imdb_genre.genre_id')
+ ->where('imdb_genre.imdb_id', $movie->id)
+ ->pluck('genre.name');
+
+ $casts = DB::connection('cinema')
+ ->table('who')
+ ->join('people', 'people.id', '=', 'who.people_id')
+ ->join('profession', 'profession.id', '=', 'who.profession_id')
+ ->where('who.imdb_id', $movie->id)
+ ->select('people.name', 'profession.name as profession')
+ ->get();
+
+ $actors = $casts->where('profession', 'actor')->take(8);
+ $directors = $casts->where('profession', 'director');
+ $screenwriters = $casts->where('profession', 'screenwriter')->take(3);
+
+ $hnStories = DB::connection('cinema')
+ ->table('links')
+ ->join('story', 'story.id', '=', 'links.story_id')
+ ->select(
+ 'story.story_id',
+ 'story.title',
+ 'story.type',
+ 'story.text',
+ 'story.score',
+ 'story.descendants',
+ 'story.time'
+ )
+ ->where('links.host', 'www.imdb.com')
+ ->where('links.field', 1)
+ ->where('links.param', $id)
+ ->orderBy('story.time', 'desc')
+ ->get();
+
+ return view('cinema_show', [
+ 'movie' => $movie,
+ 'genres' => $genres,
+ 'actors' => $actors,
+ 'directors' => $directors,
+ 'screenwriters' => $screenwriters,
+ 'hnStories' => $hnStories,
+ ]);
+ }
+
+ public function genres()
+ {
+ $genres = DB::connection('cinema')
+ ->table('genre')
+ ->select('genre.name', DB::raw('COUNT(imdb_genre.imdb_id) as count'))
+ ->join('imdb_genre', 'imdb_genre.genre_id', '=', 'genre.id')
+ ->join('imdb', 'imdb.id', '=', 'imdb_genre.imdb_id')
+ ->whereNotNull('imdb.primary_title')
+ ->whereNotNull('imdb.wiki_article')
+ ->where('imdb.title_type', 'movie')
+ ->groupBy('genre.name')
+ ->orderBy('count', 'desc')
+ ->get();
+
+ return view('genres', ['genres' => $genres]);
+ }
+
+ public function genre($name)
+ {
+ $genre = DB::connection('cinema')
+ ->table('genre')
+ ->where('name', $name)
+ ->first();
+
+ if (! $genre) {
+ abort(404);
+ }
+
+ $movies = DB::connection('cinema')
+ ->table('imdb')
+ ->select(
+ 'imdb.id',
+ 'imdb.imdb_id',
+ 'imdb.primary_title',
+ 'imdb.original_title',
+ 'imdb.start_year',
+ 'imdb.average_rating',
+ 'imdb.num_votes',
+ 'imdb.synopsis',
+ 'imdb.poster_url',
+ 'imdb.title_type',
+ 'imdb.runtime_minutes'
+ )
+ ->join('imdb_genre', 'imdb_genre.imdb_id', '=', 'imdb.id')
+ ->join('genre', 'genre.id', '=', 'imdb_genre.genre_id')
+ ->where('genre.name', $name)
+ ->whereNotNull('imdb.primary_title')
+ ->whereNotNull('imdb.wiki_article')
+ ->where('imdb.title_type', 'movie')
+ ->orderBy('imdb.average_rating', 'desc')
+ ->simplePaginate(12);
+
+ $count = DB::connection('cinema')
+ ->table('imdb')
+ ->join('imdb_genre', 'imdb_genre.imdb_id', '=', 'imdb.id')
+ ->join('genre', 'genre.id', '=', 'imdb_genre.genre_id')
+ ->where('genre.name', $name)
+ ->whereNotNull('imdb.primary_title')
+ ->whereNotNull('imdb.wiki_article')
+ ->where('imdb.title_type', 'movie')
+ ->count();
+
+ return view('genre_movies', ['movies' => $movies, 'count' => $count, 'genre_name' => $name]);
+ }
+
+ public function search(Request $request)
+ {
+ $query = $request->input('q', '');
+
+ $movies = DB::connection('cinema')
+ ->table('imdb')
+ ->select(
+ 'imdb.id',
+ 'imdb.imdb_id',
+ 'imdb.primary_title',
+ 'imdb.original_title',
+ 'imdb.start_year',
+ 'imdb.average_rating',
+ 'imdb.num_votes',
+ 'imdb.synopsis',
+ 'imdb.poster_url',
+ 'imdb.title_type',
+ 'imdb.runtime_minutes'
+ )
+ ->whereNotNull('imdb.primary_title')
+ ->whereNotNull('imdb.wiki_article')
+ ->where('imdb.title_type', 'movie')
+ ->where(function ($q) use ($query) {
+ $q->where('imdb.primary_title', 'like', '%' . $query . '%')
+ ->orWhere('imdb.original_title', 'like', '%' . $query . '%')
+ ->orWhere('imdb.synopsis', 'like', '%' . $query . '%');
+ })
+ ->simplePaginate(12);
+
+ $total = DB::connection('cinema')
+ ->table('imdb')
+ ->whereNotNull('primary_title')
+ ->whereNotNull('wiki_article')
+ ->where('title_type', 'movie')
+ ->where(function ($q) use ($query) {
+ $q->where('primary_title', 'like', '%' . $query . '%')
+ ->orWhere('original_title', 'like', '%' . $query . '%')
+ ->orWhere('synopsis', 'like', '%' . $query . '%');
+ })
+ ->count();
+
+ return view('cinema', ['movies' => $movies, 'count' => $total, 'search_query' => $query]);
+ }
+}
diff --git a/ssh/app/Http/Controllers/Controller.php b/ssh/app/Http/Controllers/Controller.php
new file mode 100644
index 0000000..a0a2a8a
--- /dev/null
+++ b/ssh/app/Http/Controllers/Controller.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
+use Illuminate\Foundation\Bus\DispatchesJobs;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Routing\Controller as BaseController;
+
+class Controller extends BaseController
+{
+ use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
+}
diff --git a/ssh/app/Http/Controllers/FeedController.php b/ssh/app/Http/Controllers/FeedController.php
new file mode 100644
index 0000000..9d20fce
--- /dev/null
+++ b/ssh/app/Http/Controllers/FeedController.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use App\Article;
+use App\Discussion;
+use App\Category;
+use App\Libraries\Helper;
+
+class FeedController extends Controller
+{
+
+ public function new()
+ {
+ // creating rss feed with our most recent 20 posts
+ $articles = Article::join('discussion', 'discussion.article_id', '=', 'view_article.id')
+ ->select('view_article.id', 'view_article.article_id', 'view_article.url', 'view_article.title', 'view_article.excerpt_html', 'view_article.impact', 'view_article.upvotes', 'view_article.comments', 'view_article.repost')
+ ->groupBy('view_article.id', 'view_article.article_id', 'view_article.url', 'view_article.title', 'view_article.excerpt_html', 'view_article.impact', 'view_article.upvotes', 'view_article.comments', 'view_article.repost')
+ ->where('view_article.created_at', '<', now()->subMinutes(30))
+ ->orderByRaw('MAX(discussion.posted_on) DESC')
+ ->take(20)
+ ->get();
+
+ return Helper::makeFeed($articles, "new");
+ }
+
+ public function mastodon()
+ {
+ $articles = Article::join('discussion', 'discussion.article_id', '=', 'view_article.id')
+ ->select('view_article.id', 'view_article.article_id', 'view_article.url', 'view_article.title', 'view_article.excerpt_html', 'view_article.impact', 'view_article.upvotes', 'view_article.comments', 'view_article.repost')
+ ->groupBy('view_article.id', 'view_article.article_id', 'view_article.url', 'view_article.title', 'view_article.excerpt_html', 'view_article.impact', 'view_article.upvotes', 'view_article.comments', 'view_article.repost')
+ ->where('view_article.created_at', '<', now()->subMinutes(30))
+ ->orderByRaw('MAX(discussion.posted_on) DESC')
+ ->take(20)
+ ->get();
+ return Helper::makeFeed($articles, "mastodon");
+ }
+ public function mastodon_test()
+ {
+ $articles = Article::join('discussion', 'discussion.article_id', '=', 'view_article.id')
+ ->select('view_article.id', 'view_article.article_id', 'view_article.url', 'view_article.title', 'view_article.excerpt_html', 'view_article.impact', 'view_article.upvotes', 'view_article.comments', 'view_article.repost')
+ ->groupBy('view_article.id', 'view_article.article_id', 'view_article.url', 'view_article.title', 'view_article.excerpt_html', 'view_article.impact', 'view_article.upvotes', 'view_article.comments', 'view_article.repost')
+ ->where('view_article.created_at', '<', now()->subMinutes(30))
+ ->orderByRaw('MAX(discussion.posted_on) DESC')
+ ->take(20)
+ ->get();
+ return Helper::makeFeed($articles, "mastodon_test");
+ }
+
+ public function popular()
+ {
+
+ $articles = new Article;
+ $articles = $articles->setTable('view_popular');
+ $articles = $articles->take(20)->get();
+ return Helper::makeFeed($articles, "popular");
+ }
+
+ public function search(Request $request) {
+ $search_unsafe = $request->input("q");
+
+ if ( "" == $search_unsafe ) {
+ $search_unsafe = "";
+ }
+
+ $search_unsafe = explode(",", $request->input("q"));
+
+ $articles = new Article;
+
+ if ( "on" == $request->input("onlypopular") ) {
+ $articles = $articles->setTable('view_popular');
+ }
+
+ foreach($search_unsafe as $q) {
+ $q = Helper::escapeLike($q);
+ $q = "%".$q."%";
+ $articles = $articles->where(function ($query) use ($q) {
+ $query->whereHas('getCategories', function ($query) use ($q){
+ $query->where('name', 'like', $q);
+ })
+ ->orWhere('title', 'like', $q)
+ ->orWhere('url', 'like', $q)
+ ->orWhere('excerpt_html', 'like', $q);
+ });
+ }
+ $count = $articles->count();
+
+ if ( "on" == $request->input("onlypopular") ) {
+ $articles = $articles->orderBy('impact', 'desc');
+ }
+ $articles = $articles->orderBy('created_at', 'desc');
+
+ return Helper::makeFeed($articles->take(20)->get(), $request->input("q"));
+ }
+}
diff --git a/ssh/app/Http/Controllers/HomeController.php b/ssh/app/Http/Controllers/HomeController.php
new file mode 100644
index 0000000..7cbc2c3
--- /dev/null
+++ b/ssh/app/Http/Controllers/HomeController.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+
+class HomeController extends Controller
+{
+ /**
+ * Create a new controller instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->middleware('auth');
+ }
+
+ /**
+ * Show the application dashboard.
+ *
+ * @return \Illuminate\Contracts\Support\Renderable
+ */
+ public function index()
+ {
+ return view('home');
+ }
+}
diff --git a/ssh/app/Http/Controllers/IndexController.php b/ssh/app/Http/Controllers/IndexController.php
new file mode 100644
index 0000000..7e7b31b
--- /dev/null
+++ b/ssh/app/Http/Controllers/IndexController.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use App\Article;
+use App\Discussion;
+use App\Category;
+use App\Libraries\Helper;
+
+class IndexController extends Controller
+{
+
+ public function index()
+ {
+ return view('index');
+ }
+
+ public function about()
+ {
+ $count_articles = DB::Select("SELECT COUNT(*) as count FROM article;")[0];
+ $count_discussions = DB::Select("SELECT COUNT(*) as count FROM discussion;")[0];
+ $count_comments = DB::Select("SELECT sum(comments) as count FROM discussion;")[0];
+ $count_upvotes = DB::Select("SELECT sum(upvotes) as count FROM discussion;")[0];
+ return view('about', [
+ "count_articles" => $count_articles->count,
+ "count_discussions" => $count_discussions->count,
+ "count_comments" => number_format($count_comments->count),
+ "count_upvotes" => number_format($count_upvotes->count)]);
+ }
+
+ public function topic( $topic )
+ {
+ $articles = new Category;
+ $articles = $articles->orWhere('name', $topic);
+ $articles = $articles->get()->first();
+ if ( is_null($articles) ) {
+ abort(404);
+ }
+ $articles = $articles->getArticles();
+ $articles = $articles->orderBy('impact', 'desc');
+ $count = $articles->count();
+ $articles = $articles->simplePaginate(10);
+
+ return view('list', ["articles" => $articles, "count" => $count]);
+ }
+
+ public function new()
+ {
+ $articles = Article::join('discussion', 'discussion.article_id', '=', 'view_article.id')
+ ->select('view_article.id', 'view_article.article_id', 'view_article.url', 'view_article.title', 'view_article.excerpt_html', 'view_article.impact', 'view_article.upvotes', 'view_article.comments', 'view_article.repost')
+ ->groupBy('view_article.id', 'view_article.article_id', 'view_article.url', 'view_article.title', 'view_article.excerpt_html', 'view_article.impact', 'view_article.upvotes', 'view_article.comments', 'view_article.repost')
+ ->orderByRaw('MAX(discussion.posted_on) DESC');
+
+ $count = $articles->count();
+ $articles = $articles->simplePaginate(10);
+
+ return view('list', ["articles" => $articles, "count" => $count]);
+ }
+
+ public function show( $id ) {
+ $articles = Article::where('id', $id);
+ $articles = $articles->simplePaginate(10);
+ $page_title = "";
+ foreach($articles as $a) {
+ $page_title = $a->title;
+ }
+ return view('list', ["articles" => $articles, "count" => 1, "page_title" => $page_title]);
+ }
+
+ public function search(Request $request) {
+ $search_unsafe = $request->input("q");
+
+ if ( "" == $search_unsafe ) {
+ $search_unsafe = "";
+ }
+
+ $search_unsafe = explode(",", $request->input("q"));
+
+ $articles = new Article;
+
+ if ( "on" == $request->input("onlypopular") ) {
+ $articles = $articles->setTable('view_popular');
+ }
+
+ foreach($search_unsafe as $q) {
+ $q = Helper::escapeLike($q);
+ $q = "%".$q."%";
+ $articles = $articles->where(function ($query) use ($q) {
+ $query->whereHas('getCategories', function ($query) use ($q){
+ $query->where('name', 'like', $q);
+ })
+ ->orWhere('title', 'like', $q)
+ ->orWhere('excerpt_html', 'like', $q);
+ });
+ }
+ $count = $articles->count();
+
+ if ( "on" == $request->input("onlypopular") ) {
+ $articles = $articles->orderBy('impact', 'desc');
+ }
+ $articles = $articles->orderBy('created_at', 'desc');
+ $articles = $articles->simplePaginate(10);
+
+ return view('list', ["articles" => $articles, "count" => $count]);
+ }
+
+ public function popular()
+ {
+ $articles = new Article;
+ $articles = $articles->setTable('view_popular');
+ $count = $articles->count();
+ $articles = $articles->simplePaginate(10);
+
+ return view('list', ["articles" => $articles, "count" => $count]);
+ }
+
+ function topicindex() {
+ $categories = Category::orderBy('name');
+ $letters = DB::select("SELECT DISTINCT LEFT(name, 1) as name FROM category ORDER BY left(name, 1);");
+
+ return view('topicindex', ['topics' => $categories, 'letters' => $letters]);
+ }
+
+ public function random() {
+ $articles = new Article;
+ $articles = $articles->inRandomOrder();
+ $count = $articles->count();
+ $articles = $articles->simplePaginate(10);
+
+ return view('list', ["articles" => $articles, "count" => $count]);
+ }
+
+ public function populartopics() {
+ $topics = DB::select("
+ SELECT
+ c.name,
+ count(c.name) AS count
+ FROM category AS c
+ JOIN
+ article_category AS ac ON c.id = ac.category_id
+ GROUP BY
+ c.name
+ ORDER BY count(c.name) DESC;");
+#echo "<pre>"; var_dump($topics);exit;
+
+ return view('topicpopular', ['topics' => $topics ]);
+ }
+}
diff --git a/ssh/app/Http/Kernel.php b/ssh/app/Http/Kernel.php
new file mode 100644
index 0000000..09ccbc9
--- /dev/null
+++ b/ssh/app/Http/Kernel.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Http;
+
+use Illuminate\Foundation\Http\Kernel as HttpKernel;
+
+class Kernel extends HttpKernel
+{
+ /**
+ * The application's global HTTP middleware stack.
+ *
+ * These middleware are run during every request to your application.
+ *
+ * @var array
+ */
+ protected $middleware = [
+ \App\Http\Middleware\TrustProxies::class,
+ \Illuminate\Http\Middleware\HandleCors::class,
+ \App\Http\Middleware\CheckForMaintenanceMode::class,
+ \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
+ \App\Http\Middleware\TrimStrings::class,
+ \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
+ ];
+
+ /**
+ * The application's route middleware groups.
+ *
+ * @var array
+ */
+ protected $middlewareGroups = [
+ 'web' => [
+ \App\Http\Middleware\EncryptCookies::class,
+ \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+ \Illuminate\Session\Middleware\StartSession::class,
+ // \Illuminate\Session\Middleware\AuthenticateSession::class,
+ \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+ \App\Http\Middleware\VerifyCsrfToken::class,
+ \Illuminate\Routing\Middleware\SubstituteBindings::class,
+ ],
+
+ 'api' => [
+ 'throttle:60,1',
+ \Illuminate\Routing\Middleware\SubstituteBindings::class,
+ ],
+ ];
+
+ /**
+ * The application's route middleware.
+ *
+ * These middleware may be assigned to groups or used individually.
+ *
+ * @var array
+ */
+ protected $routeMiddleware = [
+ 'auth' => \App\Http\Middleware\Authenticate::class,
+ 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
+ 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
+ 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
+ 'can' => \Illuminate\Auth\Middleware\Authorize::class,
+ 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
+ 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
+ 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
+ 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
+ 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
+ ];
+}
diff --git a/ssh/app/Http/Middleware/Authenticate.php b/ssh/app/Http/Middleware/Authenticate.php
new file mode 100644
index 0000000..704089a
--- /dev/null
+++ b/ssh/app/Http/Middleware/Authenticate.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Auth\Middleware\Authenticate as Middleware;
+
+class Authenticate extends Middleware
+{
+ /**
+ * Get the path the user should be redirected to when they are not authenticated.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return string|null
+ */
+ protected function redirectTo($request)
+ {
+ if (! $request->expectsJson()) {
+ return route('login');
+ }
+ }
+}
diff --git a/ssh/app/Http/Middleware/CheckForMaintenanceMode.php b/ssh/app/Http/Middleware/CheckForMaintenanceMode.php
new file mode 100644
index 0000000..35b9824
--- /dev/null
+++ b/ssh/app/Http/Middleware/CheckForMaintenanceMode.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
+
+class CheckForMaintenanceMode extends Middleware
+{
+ /**
+ * The URIs that should be reachable while maintenance mode is enabled.
+ *
+ * @var array
+ */
+ protected $except = [
+ //
+ ];
+}
diff --git a/ssh/app/Http/Middleware/EncryptCookies.php b/ssh/app/Http/Middleware/EncryptCookies.php
new file mode 100644
index 0000000..033136a
--- /dev/null
+++ b/ssh/app/Http/Middleware/EncryptCookies.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
+
+class EncryptCookies extends Middleware
+{
+ /**
+ * The names of the cookies that should not be encrypted.
+ *
+ * @var array
+ */
+ protected $except = [
+ //
+ ];
+}
diff --git a/ssh/app/Http/Middleware/RedirectIfAuthenticated.php b/ssh/app/Http/Middleware/RedirectIfAuthenticated.php
new file mode 100644
index 0000000..2395ddc
--- /dev/null
+++ b/ssh/app/Http/Middleware/RedirectIfAuthenticated.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Providers\RouteServiceProvider;
+use Closure;
+use Illuminate\Support\Facades\Auth;
+
+class RedirectIfAuthenticated
+{
+ /**
+ * Handle an incoming request.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @param \Closure $next
+ * @param string|null $guard
+ * @return mixed
+ */
+ public function handle($request, Closure $next, $guard = null)
+ {
+ if (Auth::guard($guard)->check()) {
+ return redirect(RouteServiceProvider::HOME);
+ }
+
+ return $next($request);
+ }
+}
diff --git a/ssh/app/Http/Middleware/TrimStrings.php b/ssh/app/Http/Middleware/TrimStrings.php
new file mode 100644
index 0000000..5a50e7b
--- /dev/null
+++ b/ssh/app/Http/Middleware/TrimStrings.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
+
+class TrimStrings extends Middleware
+{
+ /**
+ * The names of the attributes that should not be trimmed.
+ *
+ * @var array
+ */
+ protected $except = [
+ 'password',
+ 'password_confirmation',
+ ];
+}
diff --git a/ssh/app/Http/Middleware/TrustProxies.php b/ssh/app/Http/Middleware/TrustProxies.php
new file mode 100644
index 0000000..3e347db
--- /dev/null
+++ b/ssh/app/Http/Middleware/TrustProxies.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Middleware;
+
+#use Fideloper\Proxy\TrustProxies as Middleware;
+use Illuminate\Http\Middleware\TrustProxies as Middleware;
+use Illuminate\Http\Request;
+
+class TrustProxies extends Middleware
+{
+ /**
+ * The trusted proxies for this application.
+ *
+ * @var array|string
+ */
+ protected $proxies = [ '192.168.122.1' ];
+
+ /**
+ * The headers that should be used to detect proxies.
+ *
+ * @var int
+ */
+ protected $headers =
+ Request::HEADER_X_FORWARDED_FOR |
+ Request::HEADER_X_FORWARDED_HOST |
+ Request::HEADER_X_FORWARDED_PORT |
+ Request::HEADER_X_FORWARDED_PROTO |
+ Request::HEADER_X_FORWARDED_AWS_ELB;
+}
diff --git a/ssh/app/Http/Middleware/VerifyCsrfToken.php b/ssh/app/Http/Middleware/VerifyCsrfToken.php
new file mode 100644
index 0000000..0c13b85
--- /dev/null
+++ b/ssh/app/Http/Middleware/VerifyCsrfToken.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
+
+class VerifyCsrfToken extends Middleware
+{
+ /**
+ * The URIs that should be excluded from CSRF verification.
+ *
+ * @var array
+ */
+ protected $except = [
+ //
+ ];
+}
diff --git a/ssh/app/Libraries/Helper.php b/ssh/app/Libraries/Helper.php
new file mode 100644
index 0000000..5029a1c
--- /dev/null
+++ b/ssh/app/Libraries/Helper.php
@@ -0,0 +1,303 @@
+<?php
+namespace App\Libraries;
+use App\Libraries\Helper;
+use Carbon\Carbon;
+use Rumenx\Feed\FeedFactory;
+
+class Helper {
+ public static function escapeLike($string){
+ $search = array('%', '_');
+ $replace = array('\%', '\_');
+ $string = str_replace($search, $replace, $string);
+ $string = explode(" ", $string);
+ return implode("%", $string);
+ }
+
+ public static function formatTimestamp($timestamp) {
+ return Carbon::createFromTimestamp($timestamp)->format("Y-m-d");
+ }
+
+ public static function makeFeed($model, $title, $cache = 60) {
+
+ switch($title) {
+ case("new"):
+ $feed_title = 'Newest Articles';
+ $feed_description = 'Newest interesting articles from Wikipedia. Keep exploring.';
+ break;
+ case( "popular"):
+ $feed_title = 'Popular Articles';
+ $feed_description = 'The most popular articles. Keep exploring.';
+ break;
+ case( "mastodon"):
+ $feed_title = 'Feed for Mastodon';
+ $feed_description = 'New articles are published automatically to Mastodon.';
+ break;
+ default:
+ $feed_title = 'Search for: ' . $title;
+ $feed_description = 'All articles for "' . $title . '".';
+ break;
+ }
+ $feed_title .= " | mostdiscussed.com";
+
+ // create new feed
+ $feed = FeedFactory::create();
+
+ // multiple feeds are supported
+ // if you are using caching you should set different cache keys for your feeds
+
+ // cache the feed for $cache minutes (second parameter is optional)
+ $feed->setCache($cache, 'feed_' . $title);
+
+ // check if there is cached feed and build new only if is not
+ if (!$feed->isCached())
+ {
+
+ // set your feed's title, description, link, pubdate and language
+ $feed->setTitle($feed_title);
+ $feed->setDescription($feed_description);
+ $feed->setSubtitle($feed_description);
+ #$feed->setLogo('http://yoursite.tld/logo.jpg');
+ $feed->setLink(url('feed/' . $title));
+ $feed->setDateFormat('datetime'); // 'datetime', 'timestamp' or 'carbon'
+ $feed->setPubdate($model[0]->created_at);
+ $feed->setLang('en');
+ $feed->setShortening(false); // true or false
+
+ if ( "mastodon" == $title || "mastodon_test" == $title ) {
+ $feed->setTextLimit(500); // maximum length of description text
+ } else {
+ $feed->setTextLimit(100); // maximum length of description text
+ }
+
+ foreach ($model as $post)
+ {
+
+ $desc = ($post->excerpt_html);
+ $categories = null;
+
+ if ( "mastodon" == $title || "mastodon_test" == $title ) {
+
+ $cat_len= 0;
+
+ if ( ! $post->getCategories()->get()->isEmpty() ) {
+
+ $categories_ar = array("#MostDiscussed");
+
+ foreach( $post->getCategories()->get() as $cat ) {
+
+ // uppercase for every word in a possible multi worded hashtag
+ $tmp_cat = ucwords($cat->name);
+
+ // strip everything after / for brevity
+ if ( false !== strpos($tmp_cat, "/") )
+ $tmp_cat = substr($tmp_cat, 0, strpos($tmp_cat, "/"));
+
+ // replace any non-alphanumeric character except underscore, because
+ // it's not allowed to be used in a hashtag
+ $tmp_cat = preg_replace("/[^A-Za-z0-9_]/", '', $tmp_cat);
+
+ // trim just in case
+ $tmp_cat = trim($tmp_cat);
+
+ // if it's not empty, add it to the hashtag array
+ if ( "" != $tmp_cat )
+ $categories_ar[] = "#". $tmp_cat;
+ }
+
+ // remove possible duplicates (because stripping after "/")
+ $categories_ar = array_unique($categories_ar);
+
+ // join to one string
+ $categories = implode(" ", $categories_ar);
+
+ $cat_counter = $post->getCategories()->get()->count();
+ $cat_len = mb_strlen($categories, "UTF-8");
+ }
+
+ $link = env('APP_URL') . "/article/" . $post->id;
+
+ // max desc length is 500 - 23 (Link) - $cat_len - 2 (white spaces)
+ $max_len = 500 - 23 - $cat_len - 2;
+
+ if ( "mastodon_test" == $title ) {
+ $desc = Helper::mastodon_summary($desc, $max_len);
+ }else {
+ $desc = Helper::first_sentence($desc, $max_len);
+ #$desc = Helper::mastodon_summary($desc, $max_len);
+ }
+
+ $desc .= " " . $categories;# . $discussions;
+
+ // set item's title, author, url, pubdate, description, content, enclosure (optional)*
+ $feed->addItem([
+ 'title' => $desc, // mastofeed.org seems to ignore the description field
+ 'author' => env('APP_NAME'),
+ 'url' => $link,
+ 'link' => $link,
+ 'pubdate' => $post->created_at,
+ 'description' => $desc,
+ 'content' => $desc
+ ]);
+
+ } else {
+ if ( ! $post->getCategories()->get()->isEmpty() ) {
+ $categories = "<br>";
+ foreach( $post->getCategories()->get() as $cat ) {
+ $categories .= "<a href='". \URL::to('/topic/' . $cat->name) ."'>". $cat->name . "</a> | ";
+ }
+ $categories = rtrim($categories, " | ");
+ $desc .= "<br>Topics:";
+ $desc .= $categories;
+ }
+
+ $discussions = "<br>";
+ foreach( $post->getDiscussions()->orderBy('comments', 'desc')->get() as $dis ) {
+ $discussions .= "<a href='" . $dis->source_url . "'>" . $dis->title . "</a> | ";
+ $discussions .= Helper::formatTimestamp($dis->posted_on) . " | " . $dis->upvotes . " Upvotes | " . $dis->comments . " Comments<br>";
+ }
+ $desc .= "<br><br>Discussions:";
+ $desc .= $discussions;
+
+ // set item's title, author, url, pubdate, description, content, enclosure (optional)*
+ $feed->addItem([
+ 'title' => $post->title,
+ 'author' => env('APP_NAME'),
+ 'url' => \URL::to($post->url),
+ 'link' => \URL::to($post->url),
+ 'pubdate' => $post->created_at,
+ 'description' => $desc,
+ 'content' => $desc
+ ]);
+ }
+ }
+
+ }
+
+ // first param is the feed format
+ // optional: second param is cache duration (value of 0 turns off caching)
+ // optional: you can set custom cache key with 3rd param as string
+ $xml = $feed->render('atom', $cache, 'feed_' . $title);
+ return response($xml, 200, [
+ 'Content-Type' => 'application/xml'
+ ]);
+ }
+
+ public static function first_sentence($content, $max_len = NULL) {
+
+ $content = html_entity_decode(strip_tags($content));
+ $content = ltrim($content);
+ $pos = strpos($content, '.');
+
+ if($pos === false) {
+ if ( is_null($max_len) ) {
+ return $content;
+ } else {
+ return substr($content, 0, $max_len);
+ }
+ }
+ else {
+ return substr($content, 0, $pos+1);
+ }
+
+ }
+
+ private static function next_sentence($content, $max_len = NULL) {
+
+ $content = ltrim($content);
+ $pos = strpos($content, '.');
+
+ if($pos === false) {
+ if ( is_null($max_len) ) {
+ return $content;
+ } else {
+ return substr($content, 0, $max_len);
+ }
+ } else {
+ return substr($content, 0, $pos+1);
+ }
+
+ }
+
+ /**
+ * Make sure to toot as much text as possible while still staying below the limit of 500 chars -link (23 chars) - 2 (white spaces) - possible hashtags
+ */
+ public static function mastodon_summary($excerpt, $max_len = 475){
+
+ /**
+ * Strip HTML from Wikipedia excerpt
+ */
+ $excerpt = ltrim(html_entity_decode(strip_tags($excerpt)));
+
+ /**
+ * The toot to be returned
+ */
+ $content = "";
+
+ /**
+ * https://stackoverflow.com/questions/16377437/split-a-text-into-sentences
+ */
+ $sentences = preg_split('/(?<=[.?!])\s+(?=[a-z])/i', $excerpt);
+ echo "<pre>";
+ echo "-----------------------";
+ var_dump($excerpt);
+ var_dump($sentences);
+
+ for ( $i = 0; $i < count($sentences); $i++ ) {
+ #if ( mb_strlen($content) < $max_len && (mb_strlen($content) + mb_strlen($sentences) ) {
+ if ( mb_strlen($content) < $max_len && (mb_strlen($content) + mb_strlen($sentences) ) < $max_len ){
+
+ //var_dump(rtrim(ltrim($sentences[$i])));
+ $content .= rtrim(ltrim($sentences[$i]));
+ var_dump("ok", $max_len);
+
+ $max_len = $max_len - mb_strlen($sentences[$i]);
+ var_dump("ok", $max_len);
+
+ } else {
+ var_dump("fail", mb_strlen($content), $max_len);
+ break;
+ }
+ }
+ return $content;
+
+ echo "<pre>";
+ while ( mb_strlen($content) < $max_len ) {
+
+ /**
+ * Get next sentence
+ */
+ $next_sentence = Helper::next_sentence($excerpt, $max_len);
+ var_dump($next_sentence);
+
+ if ( "" == $next_sentence ) {
+ break;
+ }
+
+ /**
+ * Check if $content + $next_sentence is still under $max_len
+ */
+ if ( (mb_strlen($content) + mb_strlen($next_sentence)) < $max_len ) {
+
+ /**
+ * add text
+ */
+ $content .= $next_sentence;
+
+ /**
+ * Recalc $max_len
+ */
+ $max_len = $max_len - mb_strlen($next_sentence);
+
+ /**
+ * Remove sentence from excerpt
+ */
+ $excerpt = substr($excerpt, mb_strlen($next_sentence));
+
+ } else {
+ break;
+ }
+ }
+
+ return $content;
+ }
+}
diff --git a/ssh/app/Providers/AppServiceProvider.php b/ssh/app/Providers/AppServiceProvider.php
new file mode 100644
index 0000000..141751a
--- /dev/null
+++ b/ssh/app/Providers/AppServiceProvider.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Support\ServiceProvider;
+use Illuminate\Pagination\Paginator;
+
+class AppServiceProvider extends ServiceProvider
+{
+ /**
+ * Register any application services.
+ *
+ * @return void
+ */
+ public function register()
+ {
+ //
+ }
+
+ /**
+ * Bootstrap any application services.
+ *
+ * @return void
+ */
+ public function boot()
+ {
+ Paginator::useBootstrap();
+ }
+}
diff --git a/ssh/app/Providers/AuthServiceProvider.php b/ssh/app/Providers/AuthServiceProvider.php
new file mode 100644
index 0000000..3049068
--- /dev/null
+++ b/ssh/app/Providers/AuthServiceProvider.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
+use Illuminate\Support\Facades\Gate;
+
+class AuthServiceProvider extends ServiceProvider
+{
+ /**
+ * The policy mappings for the application.
+ *
+ * @var array
+ */
+ protected $policies = [
+ // 'App\Model' => 'App\Policies\ModelPolicy',
+ ];
+
+ /**
+ * Register any authentication / authorization services.
+ *
+ * @return void
+ */
+ public function boot()
+ {
+ $this->registerPolicies();
+
+ //
+ }
+}
diff --git a/ssh/app/Providers/BroadcastServiceProvider.php b/ssh/app/Providers/BroadcastServiceProvider.php
new file mode 100644
index 0000000..395c518
--- /dev/null
+++ b/ssh/app/Providers/BroadcastServiceProvider.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Support\Facades\Broadcast;
+use Illuminate\Support\ServiceProvider;
+
+class BroadcastServiceProvider extends ServiceProvider
+{
+ /**
+ * Bootstrap any application services.
+ *
+ * @return void
+ */
+ public function boot()
+ {
+ Broadcast::routes();
+
+ require base_path('routes/channels.php');
+ }
+}
diff --git a/ssh/app/Providers/EventServiceProvider.php b/ssh/app/Providers/EventServiceProvider.php
new file mode 100644
index 0000000..723a290
--- /dev/null
+++ b/ssh/app/Providers/EventServiceProvider.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Auth\Events\Registered;
+use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
+use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
+use Illuminate\Support\Facades\Event;
+
+class EventServiceProvider extends ServiceProvider
+{
+ /**
+ * The event listener mappings for the application.
+ *
+ * @var array
+ */
+ protected $listen = [
+ Registered::class => [
+ SendEmailVerificationNotification::class,
+ ],
+ ];
+
+ /**
+ * Register any events for your application.
+ *
+ * @return void
+ */
+ public function boot()
+ {
+ parent::boot();
+
+ //
+ }
+}
diff --git a/ssh/app/Providers/RouteServiceProvider.php b/ssh/app/Providers/RouteServiceProvider.php
new file mode 100644
index 0000000..527eee3
--- /dev/null
+++ b/ssh/app/Providers/RouteServiceProvider.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
+use Illuminate\Support\Facades\Route;
+
+class RouteServiceProvider extends ServiceProvider
+{
+ /**
+ * This namespace is applied to your controller routes.
+ *
+ * In addition, it is set as the URL generator's root namespace.
+ *
+ * @var string
+ */
+ protected $namespace = 'App\Http\Controllers';
+
+ /**
+ * The path to the "home" route for your application.
+ *
+ * @var string
+ */
+ public const HOME = '/home';
+
+ /**
+ * Define your route model bindings, pattern filters, etc.
+ *
+ * @return void
+ */
+ public function boot()
+ {
+ //
+
+ parent::boot();
+ }
+
+ /**
+ * Define the routes for the application.
+ *
+ * @return void
+ */
+ public function map()
+ {
+ $this->mapApiRoutes();
+
+ $this->mapWebRoutes();
+
+ //
+ }
+
+ /**
+ * Define the "web" routes for the application.
+ *
+ * These routes all receive session state, CSRF protection, etc.
+ *
+ * @return void
+ */
+ protected function mapWebRoutes()
+ {
+ Route::middleware('web')
+ ->namespace($this->namespace)
+ ->group(base_path('routes/web.php'));
+ }
+
+ /**
+ * Define the "api" routes for the application.
+ *
+ * These routes are typically stateless.
+ *
+ * @return void
+ */
+ protected function mapApiRoutes()
+ {
+ Route::prefix('api')
+ ->middleware('api')
+ ->namespace($this->namespace)
+ ->group(base_path('routes/api.php'));
+ }
+}
diff --git a/ssh/app/User.php b/ssh/app/User.php
new file mode 100644
index 0000000..e79dab7
--- /dev/null
+++ b/ssh/app/User.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace App;
+
+use Illuminate\Contracts\Auth\MustVerifyEmail;
+use Illuminate\Foundation\Auth\User as Authenticatable;
+use Illuminate\Notifications\Notifiable;
+
+class User extends Authenticatable
+{
+ use Notifiable;
+
+ /**
+ * The attributes that are mass assignable.
+ *
+ * @var array
+ */
+ protected $fillable = [
+ 'name', 'email', 'password',
+ ];
+
+ /**
+ * The attributes that should be hidden for arrays.
+ *
+ * @var array
+ */
+ protected $hidden = [
+ 'password', 'remember_token',
+ ];
+
+ /**
+ * The attributes that should be cast to native types.
+ *
+ * @var array
+ */
+ protected $casts = [
+ 'email_verified_at' => 'datetime',
+ ];
+}