├── .gitignore ├── src ├── Exceptions │ └── InvalidReportUser.php ├── ReportsServiceProvider.php ├── Models │ └── Report.php ├── Events │ ├── OnReport.php │ └── OnDeleteReport.php ├── Contracts │ ├── ReportsInterface.php │ └── ReportableInterface.php └── Traits │ ├── Reports.php │ └── Reportable.php ├── phpunit.xml ├── phpunit.xml.bak ├── tests ├── TestCase.php └── ReportableTest.php ├── LICENSE ├── migrations └── 2021_07_11_000000_create_reports_table.php ├── .php_cs.dist.php ├── composer.json ├── .php-cs-fixer.cache ├── CONTRIBUTING.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | .env 4 | .env.backup 5 | .env.production 6 | .phpactor.json 7 | .phpunit.result.cache 8 | /.fleet 9 | /.idea 10 | /.nova 11 | /.phpunit.cache 12 | /.vscode 13 | /.zed 14 | /auth.json 15 | /node_modules 16 | /public/build 17 | /public/hot 18 | /public/storage 19 | /storage/*.key 20 | /storage/pail 21 | /vendor 22 | Homestead.json 23 | Homestead.yaml 24 | Thumbs.db 25 | .vemto_settings 26 | -------------------------------------------------------------------------------- /src/Exceptions/InvalidReportUser.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | src 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /phpunit.xml.bak: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | tests 10 | 11 | 12 | 13 | 14 | src 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/ReportsServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadMigrations(); 17 | } 18 | 19 | /** 20 | * Register the service provider. 21 | * 22 | * @return void 23 | */ 24 | public function register() 25 | { 26 | // 27 | } 28 | 29 | /** 30 | * Load migrations. 31 | * 32 | * @return void 33 | */ 34 | protected function loadMigrations() 35 | { 36 | if ($this->app->runningInConsole()) { 37 | $migrationsPath = __DIR__ . '/../migrations'; 38 | 39 | $this->publishes([ 40 | $migrationsPath => database_path('migrations'), 41 | ], 'laravel-reports-migrations'); 42 | 43 | $this->loadMigrationsFrom($migrationsPath); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | set('database.default', 'testbench'); 33 | $app['config']->set('database.connections.testbench', [ 34 | 'driver' => 'sqlite', 35 | 'database' => ':memory:', 36 | 'prefix' => '', 37 | ]); 38 | } 39 | } -------------------------------------------------------------------------------- /src/Models/Report.php: -------------------------------------------------------------------------------- 1 | morphTo(); 34 | } 35 | 36 | /** 37 | * Get the user that reported on Reportable model. 38 | * 39 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 40 | */ 41 | public function reportBy() 42 | { 43 | $userModel = config('auth.providers.users.model'); 44 | 45 | return $this->belongsTo($userModel, 'user_id'); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Reza Ghasemzadeh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Events/OnReport.php: -------------------------------------------------------------------------------- 1 | reportable = $reportable; 43 | $this->report = $report; 44 | $this->reportBy = $reportBy; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /migrations/2021_07_11_000000_create_reports_table.php: -------------------------------------------------------------------------------- 1 | id(); 21 | $table->foreignId('user_id')->constrained()->onDelete('cascade'); 22 | $table->morphs('reportable'); 23 | $table->string('type')->nullable(); 24 | $table->timestamps(); 25 | 26 | $table->unique([ 27 | 'reportable_type', 28 | 'reportable_id', 29 | 'user_id', 30 | ], 'report_user_unique'); 31 | }); 32 | } 33 | 34 | /** 35 | * Reverse the migrations. 36 | * 37 | * @return void 38 | */ 39 | public function down() 40 | { 41 | Schema::dropIfExists('reports'); 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /src/Events/OnDeleteReport.php: -------------------------------------------------------------------------------- 1 | reportable = $reportable; 43 | $this->report = $report; 44 | $this->reportBy = $reportBy; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Contracts/ReportsInterface.php: -------------------------------------------------------------------------------- 1 | in([ 5 | __DIR__.'/src', 6 | __DIR__.'/tests', 7 | ]) 8 | ->name('*.php') 9 | ->notName('*.blade.php') 10 | ->ignoreDotFiles(true) 11 | ->ignoreVCS(true); 12 | 13 | return (new PhpCsFixer\Config()) 14 | ->setRules([ 15 | '@PSR12' => true, 16 | 'array_syntax' => ['syntax' => 'short'], 17 | 'ordered_imports' => ['sort_algorithm' => 'alpha'], 18 | 'no_unused_imports' => true, 19 | 'not_operator_with_successor_space' => true, 20 | 'trailing_comma_in_multiline' => true, 21 | 'phpdoc_scalar' => true, 22 | 'unary_operator_spaces' => true, 23 | 'binary_operator_spaces' => true, 24 | 'blank_line_before_statement' => [ 25 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], 26 | ], 27 | 'phpdoc_single_line_var_spacing' => true, 28 | 'phpdoc_var_without_name' => true, 29 | 'class_attributes_separation' => [ 30 | 'elements' => [ 31 | 'method' => 'one', 32 | ], 33 | ], 34 | 'method_argument_space' => [ 35 | 'on_multiline' => 'ensure_fully_multiline', 36 | 'keep_multiple_spaces_after_comma' => true, 37 | ], 38 | 'single_trait_insert_per_statement' => true, 39 | ]) 40 | ->setFinder($finder); 41 | -------------------------------------------------------------------------------- /src/Contracts/ReportableInterface.php: -------------------------------------------------------------------------------- 1 | reports()->where([ 22 | 'user_id' => $this->getKey(), 23 | ])->first(); 24 | 25 | if (!$report) { 26 | return $this->storeReport($reportable, $type); 27 | } 28 | 29 | if ($report->type == $type) { 30 | return $report; 31 | } 32 | 33 | $this->deleteReport($report, $reportable); 34 | 35 | return $this->storeReport($reportable, $type); 36 | } 37 | 38 | /** 39 | * Remove report from reportable model. 40 | * 41 | * @param ReportableInterface $reportable 42 | * @return void 43 | */ 44 | public function removeReportFrom(ReportableInterface $reportable) 45 | { 46 | $report = $reportable->reports()->where([ 47 | 'user_id' => $this->getKey(), 48 | ])->first(); 49 | 50 | if (!$report) { 51 | return; 52 | } 53 | 54 | $this->deleteReport($report, $reportable); 55 | } 56 | 57 | /** 58 | * Toggle report on reportable model. 59 | * 60 | * @param ReportableInterface $reportable 61 | * @param mixed $type 62 | * @return Report|void 63 | */ 64 | public function toggleReportOn(ReportableInterface $reportable, $type) 65 | { 66 | $report = $reportable->reports()->where([ 67 | 'user_id' => $this->getKey(), 68 | ])->first(); 69 | 70 | if (!$report) { 71 | return $this->storeReport($reportable, $type); 72 | } 73 | 74 | $this->deleteReport($report, $reportable); 75 | 76 | if ($report->type == $type) { 77 | return; 78 | } 79 | 80 | return $this->storeReport($reportable, $type); 81 | } 82 | 83 | /** 84 | * Report on reportable model. 85 | * 86 | * @param ReportableInterface $reportable 87 | * @return Report|null 88 | */ 89 | public function reportedOn(ReportableInterface $reportable) 90 | { 91 | return $reportable->reported($this); 92 | } 93 | 94 | /** 95 | * Check is reported on reportable model. 96 | * 97 | * @param ReportableInterface $reportable 98 | * @param mixed $type 99 | * @return bool 100 | */ 101 | public function isReportedOn(ReportableInterface $reportable, $type = null) 102 | { 103 | $isReported = $reportable->reports()->where([ 104 | 'user_id' => $this->getKey(), 105 | ]); 106 | 107 | if ($type) { 108 | $isReported->where([ 109 | 'type' => $type, 110 | ]); 111 | } 112 | 113 | return $isReported->exists(); 114 | } 115 | 116 | /** 117 | * Store report. 118 | * 119 | * @param ReportableInterface $reportable 120 | * @param mixed $type 121 | * @return Report 122 | */ 123 | protected function storeReport(ReportableInterface $reportable, $type) 124 | { 125 | $report = $reportable->reports()->create([ 126 | 'user_id' => $this->getKey(), 127 | 'type' => $type, 128 | ]); 129 | 130 | event(new OnReport($reportable, $report, $this)); 131 | 132 | return $report; 133 | } 134 | 135 | /** 136 | * Delete report. 137 | * 138 | * @param Report $report 139 | * @param ReportableInterface $reportable 140 | * @return bool|null 141 | */ 142 | protected function deleteReport(Report $report, ReportableInterface $reportable) 143 | { 144 | $response = $report->delete(); 145 | 146 | event(new OnDeleteReport($reportable, $report, $this)); 147 | 148 | return $response; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /tests/ReportableTest.php: -------------------------------------------------------------------------------- 1 | createUsersTable(); 23 | $this->createPostsTable(); 24 | } 25 | 26 | #[Test] 27 | public function it_can_report_on_a_model() 28 | { 29 | $user = TestUser::create(['name' => 'John Doe']); 30 | $post = TestPost::create(['title' => 'Test Post']); 31 | 32 | $report = $post->report('spam', $user); 33 | 34 | $this->assertNotNull($report); 35 | $this->assertEquals('spam', $report->type); 36 | $this->assertEquals($user->id, $report->user_id); 37 | $this->assertEquals($post->id, $report->reportable_id); 38 | $this->assertEquals(TestPost::class, $report->reportable_type); 39 | } 40 | 41 | #[Test] 42 | public function it_can_check_if_model_is_reported_by_user() 43 | { 44 | $user = TestUser::create(['name' => 'John Doe']); 45 | $post = TestPost::create(['title' => 'Test Post']); 46 | 47 | $this->assertFalse($post->isReportBy($user)); 48 | 49 | $post->report('spam', $user); 50 | 51 | $this->assertTrue($post->isReportBy($user)); 52 | $this->assertTrue($post->isReportBy($user, 'spam')); 53 | $this->assertFalse($post->isReportBy($user, 'violence')); 54 | } 55 | 56 | #[Test] 57 | public function it_can_remove_report() 58 | { 59 | $user = TestUser::create(['name' => 'John Doe']); 60 | $post = TestPost::create(['title' => 'Test Post']); 61 | 62 | $post->report('spam', $user); 63 | $this->assertTrue($post->isReportBy($user)); 64 | 65 | $post->removeReport($user); 66 | $this->assertFalse($post->isReportBy($user)); 67 | } 68 | 69 | #[Test] 70 | public function it_can_toggle_report() 71 | { 72 | $user = TestUser::create(['name' => 'John Doe']); 73 | $post = TestPost::create(['title' => 'Test Post']); 74 | 75 | // First report 76 | $report = $post->toggleReport('spam', $user); 77 | $this->assertNotNull($report); 78 | $this->assertTrue($post->isReportBy($user, 'spam')); 79 | 80 | // Toggle same type - should remove 81 | $post->toggleReport('spam', $user); 82 | $this->assertFalse($post->isReportBy($user, 'spam')); 83 | 84 | // Toggle different type - should add new report 85 | $report = $post->toggleReport('violence', $user); 86 | $this->assertNotNull($report); 87 | $this->assertTrue($post->isReportBy($user, 'violence')); 88 | } 89 | 90 | #[Test] 91 | public function it_can_get_report_summary() 92 | { 93 | $user1 = TestUser::create(['name' => 'John Doe']); 94 | $user2 = TestUser::create(['name' => 'Jane Doe']); 95 | $user3 = TestUser::create(['name' => 'Bob Smith']); 96 | $user4 = TestUser::create(['name' => 'Alice Johnson']); 97 | $post = TestPost::create(['title' => 'Test Post']); 98 | 99 | $post->report('spam', $user1); 100 | $post->report('spam', $user2); 101 | $post->report('violence', $user3); 102 | $post->report('violence', $user4); 103 | 104 | $summary = $post->reportSummary; 105 | 106 | $this->assertEquals(2, $summary['spam']); 107 | $this->assertEquals(2, $summary['violence']); 108 | } 109 | 110 | private function createUsersTable() 111 | { 112 | $this->app['db']->connection()->getSchemaBuilder()->create('users', function ($table) { 113 | $table->id(); 114 | $table->string('name'); 115 | $table->timestamps(); 116 | }); 117 | } 118 | 119 | private function createPostsTable() 120 | { 121 | $this->app['db']->connection()->getSchemaBuilder()->create('posts', function ($table) { 122 | $table->id(); 123 | $table->string('title'); 124 | $table->timestamps(); 125 | }); 126 | } 127 | } 128 | 129 | class TestUser extends Model implements ReportsInterface 130 | { 131 | use Reports; 132 | 133 | protected $table = 'users'; 134 | protected $fillable = ['name']; 135 | } 136 | 137 | class TestPost extends Model implements ReportableInterface 138 | { 139 | use Reportable; 140 | 141 | protected $table = 'posts'; 142 | protected $fillable = ['title']; 143 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Reports 2 | ![laravel-reports](https://user-images.githubusercontent.com/36597017/200645468-274bc278-f0fb-4430-a2f1-ebae4a6fa986.jpg) 3 | 4 | Laravel reports package for implementing reports (eg: Spam,Violence,Child Abuse,illegal Drugs, etc.) on Eloquent 5 | models. 6 | 7 | ## Requirements 8 | 9 | - PHP 8.2 or higher 10 | - Laravel 6.x, 7.x, 8.x, 9.x, 10.x, 11.x, or 12.x 11 | 12 | ## Installation 13 | 14 | Download package into the project using Composer. 15 | 16 | ```bash 17 | $ composer require rezaghz/laravel-reports 18 | ``` 19 | 20 | ### Registering package 21 | 22 | > Laravel 5.5 (or higher) uses Package Auto-Discovery, so doesn't require you to manually add the ServiceProvider. 23 | 24 | For Laravel 5.4 or earlier releases version include the service provider within `app/config/app.php`: 25 | 26 | ```php 27 | 'providers' => [ 28 | Rezaghz\Laravel\Reports\ReportsServiceProvider::class, 29 | ], 30 | ``` 31 | 32 | ### Database Migration 33 | 34 | If you want to make changes in migrations, publish them to your application first. 35 | 36 | ```bash 37 | $ php artisan vendor:publish --provider="Rezaghz\Laravel\Reports\ReportsServiceProvider" --tag=laravel-reports-migrations 38 | ``` 39 | 40 | Run database migrations. 41 | 42 | ```bash 43 | $ php artisan migrate 44 | ``` 45 | 46 | ## Usage 47 | 48 | ### Prepare Reports (User) Model 49 | 50 | Use `Rezaghz\Laravel\Reports\Contracts\ReportsInterface` contract in model which will perform report behavior on 51 | reportable model and implement it and use `Rezaghz\Laravel\Reports\Traits\Reports` trait. 52 | 53 | ```php 54 | use Rezaghz\Laravel\Reports\Traits\Reports; 55 | use Rezaghz\Laravel\Reports\Contracts\ReportsInterface; 56 | use Illuminate\Foundation\Auth\User as Authenticatable; 57 | 58 | class User extends Authenticatable implements ReportsInterface 59 | { 60 | use Reports; 61 | } 62 | ``` 63 | 64 | ### Prepare Reportable Model 65 | 66 | Use `Rezaghz\Laravel\Reports\Contracts\ReportableInterface` contract in model which will get report behavior and 67 | implement it and use `Rezaghz\Laravel\Reports\Traits\Reportable` trait. 68 | 69 | ```php 70 | use Illuminate\Database\Eloquent\Model; 71 | use Rezaghz\Laravel\Reports\Traits\Reportable; 72 | use Rezaghz\Laravel\Reports\Contracts\ReportableInterface; 73 | 74 | class Article extends Model implements ReportableInterface 75 | { 76 | use Reportable; 77 | } 78 | ``` 79 | 80 | ## Available Methods 81 | 82 | ### Report 83 | 84 | ```php 85 | $user->reportTo($article, 'spam'); 86 | 87 | $article->report('spam'); // current login user 88 | $article->report('spam', $user); 89 | ``` 90 | 91 | ### Remove Report 92 | 93 | Removing report of user from reportable model. 94 | 95 | ```php 96 | $user->removeReportFrom($article); 97 | 98 | $article->removeReport(); // current login user 99 | $article->removeReport($user); 100 | ``` 101 | 102 | ### Toggle Report 103 | 104 | The toggle report method will add a report to the model if the user has not reported. If a user has already reported, 105 | then it will replace the previous report with a new report. For example, if the user has reported 'spam' on the model. 106 | Now on toggles report to 'violence' then it will remove the 'spam' and stores the 'violence' report. 107 | 108 | If a user has reported `spam` then on toggle report with `spam`. It will remove the report. 109 | 110 | ```php 111 | $user->toggleReportOn($article, 'spam'); 112 | 113 | $article->toggleReport('spam'); // current login user 114 | $article->toggleReport('spam', $user); 115 | ``` 116 | 117 | ### Boolean check if user reported on model 118 | 119 | ```php 120 | $user->isReportedOn($article)); 121 | 122 | $article->is_reported; // current login user 123 | $article->isReportBy(); // current login user 124 | $article->isReportBy($user); 125 | ``` 126 | 127 | ### Report summary on model 128 | 129 | ```php 130 | $article->reportSummary(); 131 | $article->report_summary; 132 | 133 | // example 134 | $article->report_summary->toArray(); 135 | // output 136 | /* 137 | [ 138 | "spam" => 5, 139 | "violence" => 2, 140 | "illegal_drugs" => 4, 141 | "child_abuse" => 1 142 | ] 143 | */ 144 | ``` 145 | 146 | ### Get collection of users who reported on model 147 | 148 | ```php 149 | $article->reportsBy(); 150 | ``` 151 | 152 | ### Scopes 153 | 154 | Find all articles reported by user. 155 | 156 | ```php 157 | Article::whereReportedBy()->get(); // current login user 158 | 159 | Article::whereReportedBy($user)->get(); 160 | Article::whereReportedBy($user->id)->get(); 161 | ``` 162 | 163 | ### Report on Model 164 | 165 | ```php 166 | // It will return the Report object that is reported by given user. 167 | $article->reported($user); 168 | $article->reported(); // current login user 169 | $article->reported; // current login user 170 | 171 | $user->reportedOn($article); 172 | ``` 173 | 174 | ### Events 175 | 176 | On each report added `\Rezaghz\Laravel\Reports\Events\OnReport` event is fired. 177 | 178 | On each report removed `\Rezaghz\Laravel\Reports\Events\OnDeleteReport` event is fired. 179 | 180 | ## Testing 181 | 182 | Run the tests with: 183 | 184 | ```bash 185 | $ composer test 186 | ``` 187 | 188 | Or run PHPUnit directly: 189 | 190 | ```bash 191 | $ vendor/bin/phpunit 192 | ``` 193 | 194 | ## Changelog 195 | 196 | ### v2.0.0 (2025-01-08) 197 | - **BREAKING**: Updated to support Laravel 12.x 198 | - **BREAKING**: Requires PHP 8.2 or higher 199 | - Updated migration to use modern Laravel 12 patterns 200 | - Fixed method naming inconsistencies 201 | - Improved type hints and return types 202 | - Updated testing framework compatibility 203 | 204 | ### v1.0.0 (2023-09-28) 205 | - Initial release 206 | - Support for Laravel 6.x - 10.x 207 | - Basic reporting functionality 208 | -------------------------------------------------------------------------------- /src/Traits/Reportable.php: -------------------------------------------------------------------------------- 1 | morphMany(Report::class, 'reportable'); 20 | } 21 | 22 | /** 23 | * Get collection of users who reported on reportable model. 24 | * 25 | * @return \Illuminate\Support\Collection 26 | */ 27 | public function reportsBy() 28 | { 29 | $userModel = $this->resolveUserModelObj(); 30 | 31 | $userIds = $this->reports->pluck('user_id'); 32 | 33 | return $userModel::whereKey($userIds)->get(); 34 | } 35 | 36 | /** 37 | * Attribute to get collection of users who reported on reportable model. 38 | * 39 | * @return \Illuminate\Support\Collection 40 | */ 41 | public function getReportsByAttribute() 42 | { 43 | return $this->reportsBy(); 44 | } 45 | 46 | /** 47 | * Report summary. 48 | * 49 | * @return \Illuminate\Database\Eloquent\Collection|static[] 50 | */ 51 | public function reportSummary() 52 | { 53 | return $this->reports->groupBy('type')->map(function ($val) { 54 | return $val->count(); 55 | }); 56 | } 57 | 58 | /** 59 | * Report summary attribute. 60 | * 61 | * @return \Illuminate\Database\Eloquent\Collection|static[] 62 | */ 63 | public function getReportSummaryAttribute() 64 | { 65 | return $this->reportSummary(); 66 | } 67 | 68 | /** 69 | * Add report. 70 | * 71 | * @param mixed $reportType 72 | * @param mixed $user 73 | * @return Report|bool 74 | */ 75 | public function report($reportType, $user = null) 76 | { 77 | $user = $this->getUserObj($user); 78 | 79 | if ($user) { 80 | return $user->reportTo($this, $reportType); 81 | } 82 | 83 | return false; 84 | } 85 | 86 | /** 87 | * Remove report. 88 | * 89 | * @param mixed $user 90 | * @return bool 91 | */ 92 | public function removeReport($user = null) 93 | { 94 | $user = $this->getUserObj($user); 95 | 96 | if ($user) { 97 | return $user->removeReportFrom($this); 98 | } 99 | 100 | return false; 101 | } 102 | 103 | /** 104 | * Toggle Report. 105 | * 106 | * @param mixed $reportType 107 | * @param mixed $user 108 | * @return Report|void 109 | */ 110 | public function toggleReport($reportType, $user = null) 111 | { 112 | $user = $this->getUserObj($user); 113 | 114 | if ($user) { 115 | return $user->toggleReportOn($this, $reportType); 116 | } 117 | } 118 | 119 | /** 120 | * Report on reportable model by user. 121 | * 122 | * @param mixed $user 123 | * @return Report|null 124 | */ 125 | public function reported($user = null) 126 | { 127 | $user = $this->getUserObj($user); 128 | 129 | return $this->reports->where('user_id', $user->getKey())->first(); 130 | } 131 | 132 | /** 133 | * Report on reportable model by user. 134 | * 135 | * @return Report|null 136 | */ 137 | public function getReportedAttribute() 138 | { 139 | return $this->reported(); 140 | } 141 | 142 | /** 143 | * Check is reported by user. 144 | * 145 | * @param mixed $user 146 | * @param mixed $type 147 | * @return bool 148 | */ 149 | public function isReportBy($user = null, $type = null) 150 | { 151 | $user = $this->getUserObj($user); 152 | 153 | if ($user) { 154 | return $user->isReportedOn($this, $type); 155 | } 156 | 157 | return false; 158 | } 159 | 160 | /** 161 | * Check is reported by user. 162 | * 163 | * @return bool 164 | */ 165 | public function getIsReportedAttribute() 166 | { 167 | return $this->isReportBy(); 168 | } 169 | 170 | /** 171 | * Fetch records that are reported by a given user. 172 | * 173 | * @param \Illuminate\Database\Eloquent\Builder $query 174 | * @param string $type 175 | * @param null|int|ReportsInterface $userId 176 | * @return \Illuminate\Database\Eloquent\Builder 177 | * 178 | * @throw InvalidReportUser 179 | * @todo think about method name 180 | * 181 | */ 182 | public function scopeWhereReportedBy(Builder $query, $userId = null, $type = null) 183 | { 184 | $user = null; 185 | 186 | try { 187 | $user = $this->getUserObj($userId); 188 | } catch (InvalidReportUser $e) { 189 | if (!$user && !$userId) { 190 | throw InvalidReportUser::notDefined(); 191 | } 192 | } 193 | 194 | $userId = ($user) ? $user->getKey() : $userId; 195 | 196 | return $query->whereHas('reports', function ($innerQuery) use ($userId, $type) { 197 | $innerQuery->where('user_id', $userId); 198 | 199 | if ($type) { 200 | $innerQuery->where('type', $type); 201 | } 202 | }); 203 | } 204 | 205 | /** 206 | * Get user model. 207 | * 208 | * @param mixed $user 209 | * @return ReportsInterface 210 | * 211 | * @throw \Rezaghz\Laravel\Reports\Exceptions\InvalidReportUser 212 | */ 213 | private function getUserObj($user = null) 214 | { 215 | if (!$user && auth()->check()) { 216 | return auth()->user(); 217 | } 218 | 219 | if ($user instanceof ReportsInterface) { 220 | return $user; 221 | } 222 | 223 | if (!$user) { 224 | throw InvalidReportUser::notDefined(); 225 | } 226 | 227 | throw InvalidReportUser::invalidReportByUser(); 228 | } 229 | 230 | /** 231 | * Retrieve User's model class name. 232 | * 233 | * @return \Illuminate\Contracts\Auth\Authenticatable 234 | */ 235 | private function resolveUserModelObj() 236 | { 237 | return config('auth.providers.users.model'); 238 | } 239 | } 240 | --------------------------------------------------------------------------------