2020-04-29 17:15:54 +00:00
< ? php
2020-10-10 16:30:26 +00:00
/*
* Copyright © 2020 Miguel Nogueira
*
* This file is part of Raspberry Staff Manager .
*
* Raspberry Staff Manager is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Raspberry Staff Manager is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Raspberry Staff Manager . If not , see < https :// www . gnu . org / licenses />.
*/
2020-04-29 17:15:54 +00:00
namespace App\Http\Controllers ;
2020-05-08 07:10:25 +00:00
use App\Application ;
2020-06-26 23:32:33 +00:00
use App\Events\ApplicationDeniedEvent ;
2021-03-31 18:39:42 +00:00
use App\Facades\JSON ;
2020-06-26 23:32:33 +00:00
use App\Notifications\ApplicationMoved ;
2020-10-10 16:30:26 +00:00
use App\Notifications\NewApplicant ;
use App\Response ;
use App\User ;
use App\Vacancy ;
use ContextAwareValidator ;
2020-04-29 17:15:54 +00:00
use Illuminate\Http\Request ;
2020-05-08 07:10:25 +00:00
use Illuminate\Support\Facades\Auth ;
2020-06-26 23:32:33 +00:00
use Illuminate\Support\Facades\Log ;
2020-04-29 17:15:54 +00:00
class ApplicationController extends Controller
{
2021-01-29 16:56:29 +00:00
2021-03-31 18:39:42 +00:00
2020-12-07 17:48:15 +00:00
private function canVote ( $votes ) : bool
2020-05-29 23:20:39 +00:00
{
$allvotes = collect ([]);
2020-10-10 16:30:26 +00:00
foreach ( $votes as $vote ) {
if ( $vote -> userID == Auth :: user () -> id ) {
2020-05-29 23:20:39 +00:00
$allvotes -> push ( $vote );
}
}
2021-07-20 09:32:43 +00:00
return ! (( $allvotes -> count () == 1 ));
2020-05-29 23:20:39 +00:00
}
2020-04-30 15:38:54 +00:00
2020-05-11 15:44:47 +00:00
public function showUserApps ()
2020-04-30 15:38:54 +00:00
{
2020-05-11 15:44:47 +00:00
return view ( 'dashboard.user.applications' )
-> with ( 'applications' , Auth :: user () -> applications );
2020-04-30 15:55:14 +00:00
}
2020-07-16 20:21:28 +00:00
public function showUserApp ( Request $request , Application $application )
2020-05-22 02:49:16 +00:00
{
2021-07-20 09:32:43 +00:00
$this -> authorize ( 'view' , $application );
if ( ! is_null ( $application )) {
return view ( 'dashboard.user.viewapp' )
-> with (
[
'application' => $application ,
'comments' => $application -> comments ,
'structuredResponses' => json_decode ( $application -> response -> responseData , true ),
'formStructure' => $application -> response -> form ,
'vacancy' => $application -> response -> vacancy ,
'canVote' => $this -> canVote ( $application -> votes ),
]
);
} else {
$request -> session () -> flash ( 'error' , __ ( 'The application you requested could not be found.' ));
2020-05-22 02:49:16 +00:00
}
2021-07-20 09:32:43 +00:00
return redirect () -> back ();
2020-05-22 02:49:16 +00:00
}
2021-03-31 02:55:09 +00:00
public function showAllApps ( Request $request )
2020-07-11 01:43:59 +00:00
{
2021-07-20 09:32:43 +00:00
$this -> authorize ( 'viewAny' , Application :: class );
2021-03-31 02:55:09 +00:00
2021-07-20 09:32:43 +00:00
return view ( 'dashboard.appmanagement.all' );
2021-03-31 02:55:09 +00:00
2020-07-11 01:43:59 +00:00
}
2020-05-08 05:06:24 +00:00
public function renderApplicationForm ( Request $request , $vacancySlug )
{
$vacancyWithForm = Vacancy :: with ( 'forms' ) -> where ( 'vacancySlug' , $vacancySlug ) -> get ();
2020-06-26 23:32:33 +00:00
$firstVacancy = $vacancyWithForm -> first ();
2021-03-31 18:39:42 +00:00
if ( ! $vacancyWithForm -> isEmpty () && $firstVacancy -> vacancyCount !== 0 && $firstVacancy -> vacancyStatus == 'OPEN' ) {
2020-05-08 05:06:24 +00:00
return view ( 'dashboard.application-rendering.apply' )
-> with ([
'vacancy' => $vacancyWithForm -> first (),
2020-10-10 16:30:26 +00:00
'preprocessedForm' => json_decode ( $vacancyWithForm -> first () -> forms -> formStructure , true ),
2020-05-08 05:06:24 +00:00
]);
2020-10-10 16:30:26 +00:00
} else {
2021-07-20 09:32:43 +00:00
abort ( 404 , __ ( 'The application you\'re looking for could not be found or it is currently unavailable.' ));
2020-05-08 05:06:24 +00:00
}
}
2020-05-08 07:10:25 +00:00
public function saveApplicationAnswers ( Request $request , $vacancySlug )
{
$vacancy = Vacancy :: with ( 'forms' ) -> where ( 'vacancySlug' , $vacancySlug ) -> get ();
2021-03-31 18:39:42 +00:00
if ( $vacancy -> isEmpty ()) {
2021-07-20 09:32:43 +00:00
return redirect ()
-> back ()
-> with ( 'error' , __ ( 'This vacancy doesn\'t exist; Please use the proper buttons to apply to one.' ));
2021-03-31 18:39:42 +00:00
}
2020-10-10 16:30:26 +00:00
if ( $vacancy -> first () -> vacancyCount == 0 || $vacancy -> first () -> vacancyStatus !== 'OPEN' ) {
2020-06-26 23:32:33 +00:00
2021-03-31 18:39:42 +00:00
return redirect ()
-> back ()
2021-07-20 09:32:43 +00:00
-> with ( 'error' , __ ( 'This application is unavailable' ));
2020-06-26 23:32:33 +00:00
}
2020-05-08 07:10:25 +00:00
Log :: info ( 'Processing new application!' );
$formStructure = json_decode ( $vacancy -> first () -> forms -> formStructure , true );
2021-07-20 09:32:43 +00:00
$responseValidation = ContextAwareValidator :: getResponseValidator ( $request -> all (), $formStructure );
$applicant = Auth :: user ();
2021-03-31 18:39:42 +00:00
// API users may specify ID 1 for an anonymous application, but they'll have to submit contact details for it to become active.
// User ID 1 is exempt from application rate limits
2020-05-08 07:10:25 +00:00
Log :: info ( 'Built response & validator structure!' );
2021-03-31 18:39:42 +00:00
if ( ! $responseValidation -> get ( 'validator' ) -> fails ()) {
2020-05-08 07:10:25 +00:00
$response = Response :: create ([
'responseFormID' => $vacancy -> first () -> forms -> id ,
'associatedVacancyID' => $vacancy -> first () -> id , // Since a form can be used by multiple vacancies, we can only know which specific vacancy this response ties to by using a vacancy ID
2020-10-10 16:30:26 +00:00
'responseData' => $responseValidation -> get ( 'responseStructure' ),
2020-05-08 07:10:25 +00:00
]);
2021-03-31 18:39:42 +00:00
Log :: info ( 'Registered form response!' , [
'applicant' => $applicant -> name ,
'vacancy' => $vacancy -> first () -> vacancyName
]);
2020-05-08 07:10:25 +00:00
2020-06-26 23:32:33 +00:00
$application = Application :: create ([
2021-03-31 18:39:42 +00:00
'applicantUserID' => $applicant -> id ,
2020-05-08 07:10:25 +00:00
'applicantFormResponseID' => $response -> id ,
'applicationStatus' => 'STAGE_SUBMITTED' ,
]);
2021-03-31 18:39:42 +00:00
Log :: info ( 'Submitted an application!' , [
'responseID' => $response -> id ,
'applicant' => $applicant -> name
]);
2020-05-08 07:10:25 +00:00
2020-10-10 16:30:26 +00:00
foreach ( User :: all () as $user ) {
if ( $user -> hasRole ( 'admin' )) {
$user -> notify (( new NewApplicant ( $application , $vacancy -> first ())) -> delay ( now () -> addSeconds ( 10 )));
}
2020-06-26 23:32:33 +00:00
}
2021-07-20 09:32:43 +00:00
$request -> session () -> flash ( 'success' , __ ( 'Thank you for your application! It will be reviewed as soon as possible.' ));
2021-03-31 18:39:42 +00:00
return redirect ( route ( 'showUserApps' ));
2020-05-08 07:10:25 +00:00
}
2021-03-31 18:39:42 +00:00
Log :: warning ( 'Application form for ' . $applicant -> name . ' contained errors, resetting!' );
return redirect ()
-> back ()
2021-07-20 09:32:43 +00:00
-> with ( 'error' , __ ( 'There are one or more errors in your application. Please make sure none of your fields are empty, since they are all required.' ));
2020-05-08 07:10:25 +00:00
}
2020-05-22 02:49:16 +00:00
2020-09-02 19:52:56 +00:00
public function updateApplicationStatus ( Request $request , Application $application , $newStatus )
2020-05-22 02:49:16 +00:00
{
2021-03-31 18:39:42 +00:00
$messageIsError = false ;
2021-07-20 09:32:43 +00:00
$this -> authorize ( 'update' , Application :: class );
2021-03-31 18:39:42 +00:00
2020-05-22 02:49:16 +00:00
2020-10-10 16:30:26 +00:00
switch ( $newStatus ) {
2020-07-16 20:21:28 +00:00
case 'deny' :
2020-05-22 02:49:16 +00:00
2020-07-16 20:21:28 +00:00
event ( new ApplicationDeniedEvent ( $application ));
2021-07-20 09:32:43 +00:00
$message = __ ( " Application denied successfully. " );
2021-03-31 18:39:42 +00:00
2020-07-16 20:21:28 +00:00
break ;
2020-05-22 02:49:16 +00:00
2020-07-16 20:21:28 +00:00
case 'interview' :
2021-03-31 18:39:42 +00:00
Log :: info ( ' Moved application ID ' . $application -> id . 'to interview stage!' );
2021-07-20 09:32:43 +00:00
$message = __ ( 'Application moved to interview stage!' );
2020-06-26 23:32:33 +00:00
2021-03-31 18:39:42 +00:00
$application -> setStatus ( 'STAGE_INTERVIEW' );
2020-07-16 20:21:28 +00:00
$application -> user -> notify ( new ApplicationMoved ());
2021-03-31 18:39:42 +00:00
2020-07-16 20:21:28 +00:00
break ;
2020-05-22 02:49:16 +00:00
2020-07-16 20:21:28 +00:00
default :
2021-07-20 09:32:43 +00:00
$message = __ ( " There are no suitable statuses to update to. " );
2021-03-31 18:39:42 +00:00
$messageIsError = true ;
}
2020-05-22 02:49:16 +00:00
return redirect () -> back ();
}
2020-07-12 16:01:33 +00:00
public function delete ( Request $request , Application $application )
{
2021-07-20 09:32:43 +00:00
$this -> authorize ( 'delete' , $application );
$application -> delete (); // observers will run, cleaning it up
2020-07-16 20:21:28 +00:00
2021-07-20 09:32:43 +00:00
return redirect ()
-> back ()
-> with ( 'success' , __ ( 'Application deleted. Comments, appointments and responses have also been deleted.' ));
2021-03-31 18:39:42 +00:00
2020-07-12 16:01:33 +00:00
}
2020-04-29 17:15:54 +00:00
}