Skip to content

Instantly share code, notes, and snippets.

@1mursaleen
Created March 2, 2017 12:23
Show Gist options
  • Save 1mursaleen/2cad127855e32f94bc21602d9a23b092 to your computer and use it in GitHub Desktop.
Save 1mursaleen/2cad127855e32f94bc21602d9a23b092 to your computer and use it in GitHub Desktop.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use View;
use \DB as DB;
use App\Http\Requests\PostQuestion;
use App\Http\Requests\CallDibs;
use App\Http\Requests\AddNote;
use DateTime;
use Carbon\Carbon;
use App\Question as Question;
use App\Answer as Answer;
use App\User as User;
use App\Dib as Dib;
use App\Note as Note;
class QuestionsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$questions = Question::orderBy('id', 'desc')->paginate(20);
return view('questions.index', ['questions' => $questions]);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('questions.post');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(PostQuestion $request)
{
// Check if the question already exists then create.
$question = Question::firstOrCreate([
'user_id' => Auth::id(),
'username' => Auth::user()->username,
'title' => $request->input('title'),
'description' => $request->input('description'),
'subject' => $request->input('subject'),
'due_at' => $request->input('date'),
'price' => $request->input('price')
]);
// format URL
$title = $request->input('title');
$title = preg_replace('/[^A-Za-z0-9\-\ ]/', '', $title);
$title = str_slug($title, '-');
// create URL
$question->url = 'question' . '-' . $title . '-' . 'hb' . uniqid();
$question->save();
// Increment User's Question_posted record.
$user = Auth::user();
$user->questions_posted = ++$user->questions_posted;
// Try to save user else revert storeQuetion and abort.
try {
$user->save();
} catch (Exception $e) {
$question->forceDelete();
return response()->json(["error" => "Internal server error, Contact support."], 500);
}
// Get Files
$files = request()->file();
// List of malicious extensions that should not be accepted.
$malicious_extensions = array('exe', 'pif', 'application', 'gadget', 'msi', 'msp', 'com', 'scr', 'hta', 'cpl', 'msc', 'jar', 'bat', 'cmd', 'vb', 'vbs', 'vbe', 'js', 'jse', 'ws', 'wsf', 'wsc', 'wsh', 'ps1', 'ps1xml', 'ps2', 'ps2xml', 'psc1', 'psc2', 'msh', 'msh1', 'msh2', 'mshxml', 'msh1xml', 'msh2xml', 'scf', 'lnk', 'inf', 'reg');
// foreach file: sanitize filename, store on disk, insert database record.
foreach($files as $file)
{
// check: is successfully uploded && is acceptable size && is not malicious
if ($file->isValid()
&& (filesize($file) < 26000000)
&& ! in_array($file->extension(), $malicious_extensions))
{
try
{
// Get original file name + extension.
$original_name_ext = $file->getClientOriginalName();
// Get only original name
$original_name = pathinfo($original_name_ext, PATHINFO_FILENAME);
// Trim special characters and whitespaces from the beginning and end of the string
$trimmed_name = trim($original_name);
// Remove all whitespaces
$continuous_name = preg_replace('/\s+/', '_', $trimmed_name);
// Remove all special characters
$clean_name = preg_replace('/[^A-Za-z0-9\_]/', '', $continuous_name);
// Get substring of name if strlen > 150
$substr_name = substr($clean_name,0,150);
// Name: add uniqueID and guessed Extension.
$extension = $file->extension(); if(!$extension){$extension = 'txt';}
$filename = $substr_name . '_hb' . uniqid() . '.' . $extension;
// return File::mimeType($file);
// Store file
$file->storeAs('Question_Files/question_id_'.$question->id, $filename);
// Database entry (Table: question_files)
DB::table('question_files')->insert([
'user_id' => $user->id,
'question_id' => $question->id,
'filename' => $filename
]);
}
catch (Exception $e)
{
return $this->revertStore($question);
}
}
}
}
public function revertStore(Question $question)
{
// Decrement back User's Question_posted record.
$user = Auth::user();
$user->questions_posted = --$user->questions_posted;
$user->save();
// Revert Question.
$question->forceDelete();
// Delete Question directory from Question_Files directory.
$directory = 'Question_Files/question_id_' . $question->id;
Storage::deleteDirectory($directory);
return response()->json(["error" => "There was a problem with the files, See FAQ for Files."], 403);
}
/**
* Display the specified Question.
*
* @param string $url
* @return \Illuminate\Http\Response
*/
public function show($url)
{
// Get questions, including withdrawn_Questions
$question = Question::withTrashed()->where('url', $url)->firstOrFail();
// Normal Behaviour
if (!$question->trashed())
{
// Determine whether this user has already called dib.
$user_has_called_dib = Dib::where('question_id', $question->id)->where('user_id', Auth::id())->first();
// Get relevant dibs
$dibs = Dib::where('question_id', $question->id)->whereNotIn('status', [1])->get();
// Set $accepted_dib to null by default
$accepted_dib = NULL;
// Set submitted_answer to null by default.
$submitted_answer = NULL;
// Check: if question_status is 'pending'.
if ($question->status != 0) {
// Get accepted dib.
$accepted_dib = Dib::where('question_id', $question->id)->where('status', 1)->first();
}
// Check: if question_status is 'answer_submitted'.
if ($question->status == 2) {
// Get submitted answer.
$submitted_answer = Answer::where('answerable_id', $question->id)
->where('answerable_type', 'App\Question')->first();
}
// Get relevant files.
$files = DB::table('question_files')->where('question_id', $question->id)->get();
return view('questions.view', [
'question' => $question,
'dibs' => $dibs,
// Get relevant notes.
'notes' => $question->notes,
'files' => $files,
// Get relevant answers.
'answers' => $question->answers,
'user_has_called_dib' => $user_has_called_dib,
'accepted_dib' => $accepted_dib,
'submitted_answer' => $submitted_answer,
'display' => ""
]);
}
// Owner's Withdrawn/softDeleted Question
elseif ($question->trashed() && Auth::id() == $question->user_id)
{
// Loading relevant notes
$notes = $question->notes;
// Loading relevant Dibs
$dibs = Dib::where('question_id', $question->id)->get();
return view('questions.withdrawn', ['question' => $question, 'dibs' => $dibs, 'notes' => $notes]);
}
// Question not found or User ain't the Owner
else
{
abort(404);
}
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
/**
* softDelete question.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function withdraw($url)
{
// Get questions: including withdrawn_questions.
$question = Question::withTrashed()->where('url', $url)->firstOrFail();
// Fail safe: if question already withdrawn then show withdrawn_question.
if ($question->trashed())
{
return $this->show($url);
}
// Check if this user is the Owner, and question_status is 'open'.
if (Auth::id() == $question->user_id && $question->status == 0)
{
$question->status = 4; // Update question status to withdrawn.
$question->save(); // ^
$question->delete(); // Soft_delete question.
$user = Auth::user();
$user->questions_posted = --$user->questions_posted;
$user->save();
}
else {
abort(403, 'Unauthorized');
}
return $this->show($url); // Show soft_deleted question.
}
/**
* Add note for the relevant Question.
*
* @param string $url
* @return \Illuminate\Http\Response
*/
public function addNote(AddNote $request, $url)
{
// Get Question
$question = Question::where('url', $url)->firstOrFail();
// Check if this user is the Owner of the Question.
if (Auth::id() != $question->user_id){
abort(403, "Unauthorized Action!");
}
// Search for duplicate notes.
$note_duplicate_check = Note::where('notable_id', $question->id)
->where('body', $request->body)
->where('notable_type',"App\Question")
->first();
// Show error for duplicate note.
if ($note_duplicate_check){
return view('errors.note-duplicate');
}
// Get Notes count
$note_count_check = Note::where('notable_id', $question->id)->count();
// One question cannot have more than 20 notes, show error if limit reached.
if ($note_count_check >= 20) {
return view('errors.note-maximum');
}
// Normal behavior: save and return an instance of the note to viewNote
elseif(! $note_duplicate_check && $note_count_check < 20){
$note = new Note;
$note->body = $request->body;
$note->created_at = Carbon::now();
$note->notable_id = $question->id;
$note->notable_type = "App\Question";
$note->save();
return view('notes.note',['note' => $note]);
}
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
/* public function store(PostQuestion $request)
{
$question = new Question;
$question->title = $request->input('title');
$question->description = $request->input('description');
$question->subject = $request->input('subject');
$question->due_at = $request->input('date');
$question->price = $request->input('price');
$question->user_id = Auth::id();
$question->username = User::find(Auth::id())->username;
$title = $request->input('title');
$title = preg_replace('/[^A-Za-z0-9\-\ ]/', '', $title);
$title = str_slug($title, '-');
$question->url = 'question' . '-' . $title . '-' . 'hb' . uniqid();
$question->save();
}
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment