Merge branch 'master' of ssh://git.shikiryu.com:2200/Shikiryu/journal-intime into e2e

This commit is contained in:
2020-03-16 17:01:39 +01:00
28 changed files with 960 additions and 178 deletions

View File

@@ -0,0 +1,175 @@
<?php
namespace App\Http\Controllers;
use App\Post;
use App\PostsTag;
use App\Services\ImageService;
use App\Services\TagDetectorService;
use App\Tag;
use DateTime;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
class DashboardController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
* @throws \Exception
*/
public function index()
{
setlocale(LC_TIME, 'fr_FR.utf8');
$today = new DateTime();
$user_id = Auth::user()->getAuthIdentifier();
$user = \App\User::find($user_id);
$all_counts = Post::where('user_id', $user_id)->count();
$year_counts = Post::where('user_id', $user_id)->whereYear('date_post', $today->format('Y'))->count();
$month_counts = Post::where('user_id', $user_id)
->whereYear('date_post', $today->format('Y'))
->whereMonth('date_post', $today->format('m'))->count();
$image_counts = Post::where('user_id', Auth::user()->getAuthIdentifier())
->where('image', '!=', 'null')
->count();
$posts = Post::where('user_id', $user_id)->orderBy('date_post', 'DESC')->limit(9)->get();
$today_post = Post::whereDate('date_post', '=', $today->format('Y-m-d'))
->where('user_id', $user_id)
->count();
$already = false;
if ($today_post > 0) {
$already = true;
}
return view('home', [
'already' => $already,
'must_encrypt' => $user->encrypt_messages,
'all_counts' => $all_counts,
'year_counts' => $year_counts,
'month_counts' => $month_counts,
'image_counts' => $image_counts,
'today' => $today,
'posts' => $posts,
]);
}
/**
* Edit today's entry
*/
public function edit(TagDetectorService $tag_detector)
{
/** @var Post $today_post */
$today_post = Post::whereDate('date_post', '=', (new DateTime())->format('Y-m-d'))
->where('user_id', Auth::user()->getAuthIdentifier())
->firstOrFail();
$data = request()->validate([
'message' => 'required'
]);
$today_post->deleteTags();
$tags = $tag_detector->detectFrom($data['message']);
$today_post->content = $data['message'];
$today_post->save();
$all_tags = Tag::all();
$all_tags_names = [];
foreach ($all_tags as $tag) {
$all_tags_names[$tag->id] = $tag->name;
}
foreach ($tags as $tag) {
if (in_array($tag, $all_tags_names)) {
PostsTag::create([
'post_id' => $today_post->id,
'tag_id' => array_search($tag, $all_tags_names),
]);
}
}
return Redirect::to('home')->withSuccess('Great! Form successfully submit with validation.');
}
/**
* @return \Illuminate\Http\RedirectResponse
* @throws \Exception
*/
public function delete()
{
try {
$today_post = Post::whereDate('date_post', '=', (new DateTime())->format('Y-m-d'))
->where('user_id', Auth::user()->getAuthIdentifier())
->firstOrFail();
/** @var Post $today_post */
$today_post->deleteTags();
$today_post->delete();
return Redirect::to('home')->withSuccess('Great! Your today\'s post is now deleted. You can make a new one!');
} catch (\ErrorException $e) {
return Redirect::to('home')->withErrors('Oh no! We could\'t find your today\'s post.');
}
}
/**
* @param TagDetectorService $tag_detector
* @return mixed
* @throws \Exception
*/
public function store(TagDetectorService $tag_detector, ImageService $image_service)
{
$user_id = Auth::user()->getAuthIdentifier();
$validated_data = request()->validate([
'message' => 'required',
'file' => 'file|mimes:jpeg,png,jpg,gif,svg',
]);
$data = [
'user_id' => $user_id,
'date_post' => new DateTime(),
'content' => $validated_data['message'],
];
if (!empty($validated_data['file'])) {
/** @var UploadedFile $uploaded_document */
$uploaded_document = $validated_data['file'];
$file_name = $uploaded_document->getClientOriginalName();
$uploaded_document->storeAs(Auth::user()->getFolder(), $file_name);
$image_service->makeThumbnail($uploaded_document->getRealPath(), ['width' => 300]);
$data['image'] = $file_name;
}
$tags = $tag_detector->detectFrom($data['content']);
$check = Post::create($data);
$all_tags = Tag::all();
$all_tags_names = [];
foreach ($all_tags as $tag) {
$all_tags_names[$tag->id] = $tag->name;
}
foreach ($tags as $tag) {
if (in_array($tag, $all_tags_names)) {
PostsTag::create([
'post_id' => $check->id,
'tag_id' => array_search($tag, $all_tags_names),
]);
}
}
return Redirect::to('home')->withSuccess('Great! Form successfully submit with validation.');
}
}

View File

@@ -1,99 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Post;
use App\PostsTag;
use App\Services\TagDetectorService;
use App\Tag;
use DateTime;
use http\Client\Curl\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
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()
{
setlocale(LC_TIME, 'fr_FR.utf8');
$today = new DateTime();
$user_id = Auth::user()->getAuthIdentifier();
$user = \App\User::find($user_id);
$all_counts = Post::where('user_id', $user_id)->count();
$year_counts = Post::where('user_id', $user_id)->whereYear('date_post', $today->format('Y'))->count();
$month_counts = Post::where('user_id', $user_id)
->whereYear('date_post', $today->format('Y'))
->whereMonth('date_post', $today->format('m'))->count();
$image_counts = 0; // TODO #4
$posts = Post::where('user_id', $user_id)->orderBy('date_post', 'DESC')->limit(9)->get();
$today_post = Post::whereDate('date_post', '=', $today->format('Y-m-d'))
->where('user_id', $user_id)
->count();
$already = false;
if ($today_post > 0) {
$already = true;
}
return view('home', [
'already' => $already,
'must_encrypt' => $user->encrypt_messages,
'all_counts' => $all_counts,
'year_counts' => $year_counts,
'month_counts' => $month_counts,
'image_counts' => $image_counts,
'today' => $today,
'posts' => $posts,
]);
}
public function store(TagDetectorService $tag_detector)
{
$today = new DateTime();
$data = request()->validate([
'message' => 'required'
]);
$data = [
'user_id' => Auth::user()->getAuthIdentifier(),
'date_post' => new DateTime(), // Take back the date from the form ?
'content' => $data['message'],
];
$tags = $tag_detector->detectFrom($data['content']);
$check = Post::create($data);
$all_tags = Tag::all();
$all_tags_names = [];
foreach ($all_tags as $tag) {
$all_tags_names[$tag->id] = $tag->name;
}
foreach ($tags as $tag) {
if (in_array($tag, $all_tags_names)) {
PostsTag::create([
'post_id' => $check->id,
'tag_id' => array_search($tag, $all_tags_names),
]);
}
}
return Redirect::to('home')->withSuccess('Great! Form successfully submit with validation.');
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Http\Controllers;
use App\Post;
use App\Services\ImageService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Intervention\Image\Constraint;
use Intervention\Image\Facades\Image;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class ImageController extends Controller
{
/**
* @param int $post_id
* @param string|array $options
* @param string $image
* @param ImageService $image_service
*
* @return mixed
*/
public function display($post_id, $options = 'o:full', $image, ImageService $image_service)
{
if (Auth::guest()) {
throw new UnauthorizedHttpException('Vous devez être connecté pour voir cette image.');
}
$post = Post::find($post_id);
if (Auth::user()->getAuthIdentifier() !== (int)$post->user_id) {
throw new UnauthorizedHttpException('Cette image ne vous appartient pas.');
}
$original = sprintf('%s/%s/%s', storage_path('app'), Auth::user()->getFolder(), $image);
if ('o:full' === $options) {
$img = $image_service->makeThumbnail($original);
} else {
$img = $image_service->makeThumbnail($original, ['width' => 300]);
}
return $img->response(File::extension($original));
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function gallery()
{
$posts_with_image = Post::where('user_id', Auth::user()->getAuthIdentifier())
->where('image', '!=', 'null')
->orderBy('created_at', 'desc')
->paginate(30);
return view('gallery.my', [
'posts' => $posts_with_image,
]);
}
}

View File

@@ -3,13 +3,22 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class WelcomeController extends Controller
{
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
* @throws \Exception
*/
public function index()
{
return view('welcome', [
'today' => new \DateTime(),
]);
if (Auth::guest()) {
return view('welcome', [
'today' => new \DateTime(),
]);
}
return redirect(route('dashboard'));
}
}

View File

@@ -2,7 +2,28 @@
namespace App\Http;
use App\Http\Middleware\Authenticate;
use App\Http\Middleware\CheckForMaintenanceMode;
use App\Http\Middleware\EncryptCookies;
use App\Http\Middleware\GenerateMenus;
use App\Http\Middleware\RedirectIfAuthenticated;
use App\Http\Middleware\TrimStrings;
use App\Http\Middleware\TrustProxies;
use App\Http\Middleware\VerifyCsrfToken;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
use Illuminate\Auth\Middleware\Authorize;
use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
use Illuminate\Http\Middleware\SetCacheHeaders;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Routing\Middleware\ValidateSignature;
use Illuminate\Session\Middleware\AuthenticateSession;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;
class Kernel extends HttpKernel
{
@@ -14,11 +35,11 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
TrustProxies::class,
CheckForMaintenanceMode::class,
ValidatePostSize::class,
TrimStrings::class,
ConvertEmptyStringsToNull::class,
];
/**
@@ -28,13 +49,14 @@ class Kernel extends HttpKernel
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
GenerateMenus::class,
],
'api' => [
@@ -51,15 +73,15 @@ class Kernel extends HttpKernel
* @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,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'auth' => Authenticate::class,
'auth.basic' => AuthenticateWithBasicAuth::class,
'bindings' => SubstituteBindings::class,
'cache.headers' => SetCacheHeaders::class,
'can' => Authorize::class,
'guest' => RedirectIfAuthenticated::class,
'signed' => ValidateSignature::class,
'throttle' => ThrottleRequests::class,
'verified' => EnsureEmailIsVerified::class,
];
/**
@@ -70,12 +92,12 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
StartSession::class,
ShareErrorsFromSession::class,
Authenticate::class,
ThrottleRequests::class,
AuthenticateSession::class,
SubstituteBindings::class,
Authorize::class,
];
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Lavary\Menu\Builder;
use Lavary\Menu\Menu;
class GenerateMenus
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
(new Menu)->make('menu', function (Builder $menu) {
$accueil = $menu->add('Accueil', ['route' => 'dashboard', 'class' => 'nav-item'])->nickname('home');
$accueil->link->attr(['class' => 'nav-link']);
$accueil->prepend('<i class="fe fe-home"></i> ');
$accueil->checkActivationStatus();
$stats = $menu->add('Mes statistiques', ['route' => 'stats', 'class' => 'nav-item'])->nickname('stats');
$stats->link->attr(['class' => 'nav-link']);
$stats->prepend('<i class="fe fe-trending-up"></i> ');
$stats->checkActivationStatus();
$gallery = $menu->add('Ma gallerie', ['route' => 'gallery', 'class' => 'nav-item'])->nickname('gallery');
$gallery->link->attr(['class' => 'nav-link']);
$gallery->prepend('<i class="fe fe-image"></i> ');
$gallery->checkActivationStatus();
});
return $next($request);
}
}

View File

@@ -14,16 +14,16 @@ class Post extends Model
protected $fillable = [
'content', 'image', 'date_post', 'user_id'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
];
/**
* The attributes that should be cast to native types.
*
@@ -32,4 +32,15 @@ class Post extends Model
protected $casts = [
'date_post' => 'datetime',
];
/**
* Delete this posts tags
*/
public function deleteTags()
{
$tags_to_delete = PostsTag::where('post_id', $this->id)->get();
foreach ($tags_to_delete as $tag_to_delete) {
$tag_to_delete->delete();
}
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Providers;
use App\Services\ImageService;
use Illuminate\Support\ServiceProvider;
class ImageServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->app->bind(ImageService::class);
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Auth;
use Intervention\Image\Constraint;
use Intervention\Image\Facades\Image;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ImageService
{
/**
* @param string $image path to image
* @param array $options option to make thumbnail
*
* @return \Intervention\Image\Image
*/
public function makeThumbnail($image, $options = [])
{
if (!is_readable($image)) {
throw new NotFoundHttpException();
}
$img = Image::make($image);
if (empty($options)) {
return $img;
}
$folder = dirname($img->basePath());
$file_name = basename($image);
$width = null;
if (array_key_exists('width', $options)) {
$width = $options['width'];
$file_name = sprintf('w%u-%s', $width, $file_name);
}
$height = null;
if (array_key_exists('$height', $options)) {
$height = $options['$height'];
$file_name = sprintf('h%u-%s', $height, $file_name);
}
$full_path = sprintf('%s/%s', $folder, $file_name);
if (!array_key_exists('force', $options) && is_readable($full_path)) {
return Image::make($full_path);
}
//http://image.intervention.io/getting_started/
$img->resize($width, $height, static function (Constraint $constraint) {
$constraint->aspectRatio();
})->save(sprintf('%s/%s', $folder, $file_name));
return $img;
}
}

View File

@@ -36,4 +36,10 @@ class User extends Authenticatable
protected $casts = [
'email_verified_at' => 'datetime',
];
public function getFolder()
{
$arrayHash = str_split(strtolower(md5($this->id)));
return sprintf('%s/%s', $arrayHash[0], $arrayHash[1]);
}
}