/** * restores a topic, along with its posts and views, to a section */ public static function restoreTopicToSection(\Nexus\Topic $topic, \Nexus\Section $section) { $topic->posts()->restore(); $topic->views()->restore(); $topic->restore(); $topic->section_id = $section->id; $topic->save(); }
/** * Determine if the user is authorized to make this request. * a topic can be updated by the section moderator or by an administrator * * a topic can be moved to another section if the user moderators that section or * they are an administrator * * @return bool */ public function authorize() { $return = false; if (!\Auth::check()) { $return = false; } $formName = key($this::input('form')); $formValues = $this::input('form')[$formName]; $this->session()->flash('form', $formName); // does the user moderate the section that this topic is currently in? $topic = \Nexus\Topic::findOrFail($formValues['id']); if ($topic->section->moderator->id == \Auth::id()) { $return = true; } // is the user moving the topic to a section they moderate? try { \Auth::user()->sections()->where('id', $formValues['section_id'])->firstOrFail(); } catch (\Exception $e) { $return = false; \Log::error('Topic Update - Attempt to move to unowned section ' . $e); } // if the user is an admin then we assume they can do all if (\Auth::user()->administrator) { $return = true; } return $return; }
public function test_restoreTopicToSection_restores_a_topic_and_views() { // GIVEN I have a topic with posts in a section $section = factory(Section::class, 1)->create(); $topic = factory(Topic::class, 1)->create(['section_id' => $section->id]); factory(Post::class, 20)->create(['topic_id' => $topic->id]); $topic_id = $topic->id; // and a user reads that topic $user = factory(User::class, 1)->create(); \Nexus\Helpers\ViewHelper::updateReadProgress($user, $topic); $viewsCount = $topic->views->count(); $this->assertNotEquals($viewsCount, 0); // and then that topic is deleted $topic->delete(); // check topic deleted $this->assertTrue($topic->trashed()); // and that we have no views - need to use trashed here $this->assertEquals(Topic::withTrashed()->find($topic_id)->views->count(), 0); // WHEN the topic is restored to the section \Nexus\Helpers\RestoreHelper::restoreTopicToSection($topic, $section); // check posts and views are restored $this->assertEquals($topic->views->count(), $viewsCount); // THEN the topic is restored $this->assertFalse($topic->trashed()); }
public function getMostRecentPostAttribute() { $post = null; $topicIDs = Topic::select('id')->where('section_id', $this->id)->get()->toArray(); $postID = Post::select('id')->whereIn('topic_id', $topicIDs)->orderBy('id', 'desc')->get()->first(); if ($postID) { $post = Post::find($postID->id); } return $post; }
/** * Execute the console command. * * @return mixed */ public function handle() { // we are assuming that the sysop is always the first user $this->info('Creating administrator, default section and first topic...'); $user = \Nexus\User::first(); if (!$user) { $this->info("Please enter in values for the administrator account. Don't worry You can change this later."); $username = $this->ask('Username'); $email = $this->ask('Email Address'); $password = $this->ask('Password'); $administrator = new \Nexus\User(); $administrator->username = $username; $administrator->name = 'Administrator'; $administrator->email = $email; $administrator->password = \Hash::make($password); $administrator->administrator = true; try { $administrator->save(); } catch (\Exception $e) { $this->error('Failed to add administrator ' . $e); } } else { $this->error('There is already a user account'); } $section = \Nexus\Section::first(); if (!$section) { $this->info("Please enter in values for the main menu. Don't worry You can change this later."); $title = $this->ask('Title'); $mainmenu = new \Nexus\Section(); $mainmenu->title = $title; $mainmenu->user_id = $administrator->id; try { $mainmenu->save(); } catch (\Exception $e) { $this->error('Failed to add main menu ' . $e); } } else { $this->error('There is already a main menu'); } $topic = \Nexus\Topic::first(); if (!$topic) { $this->info("Please enter in values for the first topic. Don't worry You can change this later."); $title = $this->ask('Title'); $firstTopic = new \Nexus\Topic(); $firstTopic->title = $title; $firstTopic->section_id = $mainmenu->id; try { $firstTopic->save(); } catch (\Exception $e) { $this->error('Failed to add first topic ' . $e); } } else { $this->error('There is already a topic'); } }
/** * a topic can only be restored by * the moderator of the section and destination section * * @return bool */ public function authorize() { $return = false; $currentUserID = \Auth::user()->id; $trashedTopic = \Nexus\Topic::onlyTrashed()->findOrFail($this->topic); $originalSection = \Nexus\Section::withTrashed()->findOrFail($trashedTopic->section_id); $destinationSection = \Nexus\Section::findOrFail($this->destination); if ($destinationSection->moderator->id === $currentUserID && $originalSection->moderator->id === $currentUserID) { $return = true; } else { $return = false; } return $return; }
public function test_deleting_topic_soft_deletes_its_posts() { // GIVEN we have a topic with post $topic = factory(Topic::class, 1)->create(); factory(Post::class, 20)->create(['topic_id' => $topic->id]); // we have 1 topic with 20 posts $this->assertEquals(Topic::all()->count(), 1); $this->assertEquals(Post::where('topic_id', $topic->id)->count(), 20); // WHEN we archive the topic $topic->delete(); // THEN we have no topics and no posts $this->assertEquals(Topic::all()->count(), 0); $this->assertEquals(Post::all()->count(), 0); // BUT we have 1 trashed topic and 20 trashed posts $this->assertEquals(Topic::withTrashed()->count(), 1); $this->assertEquals(Post::withTrashed()->where('topic_id', $topic->id)->count(), 20); }
public static function boot() { parent::boot(); // Attach event handler for deleting a topic Topic::deleting(function ($topic) { /* to keep a cascading delete when using softDeletes we must remove the related models here */ $children = ['posts', 'views']; Log::info("Deleting Topic {$topic->title} - {$topic->id}"); foreach ($children as $child) { if ($topic->{$child}()) { Log::info(" - removing topic->{$child}"); $topic->{$child}()->delete(); } } }); }
/** * user can delete the topic if they are the moderator or an administrator * @return bool */ public function authorize() { $return = false; $topic = \Nexus\Topic::findOrFail($this->topic); if (\Auth::check()) { $authUser = \Auth::user(); // is the user an administrator if ($authUser->administrator) { $return = true; } // or the user is the section moderator if ($authUser->id === $topic->section->moderator->id) { $return = true; } } else { $return = false; } return $return; }
public function test_deleting_section_soft_deletes_its_topics() { // GIVEN we have a user $user = factory(User::class, 1)->create(); // AND we have a section $section = factory(Section::class, 1)->create(['parent_id' => null, 'user_id' => $user->id]); // AND that section has topics factory(Topic::class, 10)->create(['section_id' => $section->id]); $topicsInSectionCount = $section->topics->count(); $topicCount = Topic::all()->count(); // WHEN we delete that section $section->delete(); // THEN the total number of topics is reduced by the number of topics // belonging to the original section $topicCountAfterDeletion = Topic::all()->count(); $this->assertEquals($topicCount - $topicsInSectionCount, $topicCountAfterDeletion); // AND the count of topics for that section is now zero $this->assertEquals(Topic::where('section_id', $section->id)->count(), 0); // BUT that section has soft deleted topics with match the orignal count $this->assertEquals(Topic::withTrashed()->where('section_id', $section->id)->count(), $topicsInSectionCount); }
public function authorize() { $return = false; $topic = Topic::findOrFail($this::input('topic_id')); $section = Section::findOrFail($topic->section_id); if (\Auth::check()) { $authUser = \Auth::user(); // is the user an administrator if ($authUser->administrator) { $return = true; } // OR is the user the moderator if ($authUser->id === $section->moderator->id) { $return = true; } // OR is the topic NOT ready only if (!$topic->readonly) { $return = true; } } else { $return = false; } return $return; }
public function getTrashedTopicsAttribute() { /* @todo: why does the hasManyThrough not work here? return $this->hasManyThrough('Nexus\Topic', 'Nexus\Section', 'user_id', 'section_id'); */ $sectionIDs = $this->sections->pluck('id')->toArray(); $trashedTopics = Topic::onlyTrashed()->whereIn('section_id', $sectionIDs)->get(); return $trashedTopics; }
private function migrateTopics() { $this->info('Importing Topics'); $errorCount = 0; if (!\Nexus\Topic::first()) { $count = \DB::select('select count(topic_id) as count from topictable')[0]->count; $this->line("Found {$count} topics"); $bar = $this->output->createProgressBar($count); $classicTopics = \DB::table('topictable')->get(); foreach ($classicTopics as $classicTopic) { $newTopic = new \Nexus\Topic(); $newTopic->id = $classicTopic->topic_id; $newTopic->title = $classicTopic->topic_title; $newTopic->intro = $classicTopic->topic_description; $newTopic->section_id = $classicTopic->section_id; $newTopic->weight = $classicTopic->topic_weight; if ($classicTopic->topic_readonly === 'n') { $newTopic->readonly = false; } else { $newTopic->readonly = true; } if ($classicTopic->topic_annon === 'n') { $newTopic->secret = false; } else { $newTopic->secret = true; } try { $newTopic->save(); $bar->advance(); } catch (\Exception $e) { $errorCount++; \Log::error('Nexus:upgrade - Failed to import topic: ' . $e); } } $bar->finish(); unset($classicTopics); if ($errorCount) { $this->error("\nFailed to import {$errorCount} posts. See log for details"); } $this->info("\nTopics Complete\n"); } else { $this->error('Upgrade: found existing topics - skipping Topics'); } }
public function topic(Requests\topic\RestoreRequest $request, $id) { $trashedTopic = \Nexus\Topic::onlyTrashed()->findOrFail($id); $destinationSection = \Nexus\Section::findOrFail($request->destination); \Nexus\Helpers\RestoreHelper::restoreTopicToSection($trashedTopic, $destinationSection); $redirect = action('Nexus\\SectionController@show', ['id' => $destinationSection->id]); return redirect($redirect); }
/** * * toggles a users subscription to the topic */ public function updateSubscription(Requests\Topic\SubscriptionRequest $request, $id) { $input = $request->all(); $topic = \Nexus\Topic::findOrFail($id); if ($input['command'] === 'subscribe') { \Nexus\Helpers\ViewHelper::subscribeToTopic(\Auth::user(), $topic); $message = '**Subscribed!** _Catch-up_ will return you here when new comments are added.'; } else { \Nexus\Helpers\ViewHelper::unsubscribeFromTopic(\Auth::user(), $topic); $message = '**Unsubscribed!** New comments here will be hidden from _Catch-up_.'; } \Nexus\Helpers\FlashHelper::showAlert($message, 'success'); return redirect()->route('topic.show', ['id' => $topic->id]); }