diff --git a/LICENSE.md b/LICENSE.md index 99fc78d..9623e5a 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,21 +1,6 @@ The MIT License (MIT) - -Copyright (c) coolsam - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Copyright (c) 2025 Hadi Alharbi +This package is developed based on the nested-comments package by Sam Maosa. Special thanks to Sam Maosa for their foundational work. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 99ce38c..136c349 100644 --- a/README.md +++ b/README.md @@ -1,420 +1,92 @@ -# Filament Nested Comments & Emoji Reactions +# 💬 التعليقات المتداخلة وردود الفعل باستخدام Filament (مع دعم اللغة العربية والـ RTL) -[![Latest Version on Packagist](https://img.shields.io/packagist/v/coolsam/nested-comments.svg?style=flat-square)](https://packagist.org/packages/coolsam/nested-comments) -[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/coolsam726/nested-comments/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/coolsam726/nested-comments/actions?query=workflow%3Arun-tests+branch%3Amain) -[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/coolsam726/nested-comments/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/coolsam726/nested-comments/actions?query=workflow%3A"Fix+PHP+Code+Styling"+branch%3Amain) -[![GitHub PHPStan Action Status](https://img.shields.io/github/actions/workflow/status/coolsam726/nested-comments/phpstan.yml?branch=main&label=phpstan&style=flat-square)](https://github.com/coolsam726/nested-comments/actions?query=workflow%3APHPStan+branch%3Amain) -[![Total Downloads](https://img.shields.io/packagist/dt/coolsam/nested-comments.svg?style=flat-square)](https://packagist.org/packages/coolsam/nested-comments) +[![Packagist](https://img.shields.io/packagist/v/hadialharbi/nested-comments.svg?style=flat-square)](https://packagist.org/packages/hadialharbi/nested-comments) +هذه الحزمة مبنية على عمل رائع قام به [@coolsam726](https://github.com/coolsam726) في حزمته الأصلية [coolsam/nested-comments](https://github.com/coolsam726/nested-comments) — له كل الشكر والتقدير على هذا الأساس القوي والمتين. تم تطوير هذه النسخة لتدعم اللغة العربية والاتجاه من اليمين لليسار RTL، مع تحسينات على مستوى الواجهة والوظائف. -This package allows you to incorporate comments and replies in your Filament forms, infolists, pages, widgets etc, or even simply in your livewire components. Comment replies can be nested as deep as you want, using the Nested Set data structure. Additionally, the package comes with a Reactions feature to enable your users to react to any of your models (e.g comments or posts) with selected emoji reactions. +## ✅ الجديد في هذه النسخة -![image](https://github.com/user-attachments/assets/2900e2a4-9ad2-40e2-8819-2650b6d70803) +* ✅ دعم **اللغة العربية** والـ **RTL** بشكل كامل. +* ✅ دعم تعديل التعليقات مباشرة من خلال Livewire. +* ✅ دعم حذف التعليق. +* ✅ التحقق من صلاحية المستخدم قبل السماح بالتعديل أو الحذف. +* ✅ إرسال حدث `refresh` لتحديث الواجهة بعد حذف التعليق. +* ✅ تحسين تجربة المستخدم العربي بصريًا ونصيًا. +* ✅ دمج PHPUnit لاختبار الحزمة بكفاءة. -## Installation +## ✅ دمج PHPUnit -You can install the package via composer: +تم إعداد اختبار الحزمة باستخدام [orchestra/testbench](https://github.com/orchestral/testbench): -```bash -composer require coolsam/nested-comments -``` +* إعداد بيئة Laravel معزولة داخل `TestCase`. +* إنشاء قاعدة بيانات مؤقتة لتشغيل الاختبارات. +* اختبار أولي ناجح يتحقق من إنشاء تعليق. +* إصلاحات لمشاكل `migrations` و`macros`. -Run the installation command and follow the prompts: +لتشغيل الاختبارات: ```bash -php artisan nested-comments:install -``` -During the installation, you will be asked if you would like to publish and replace the config file. -This is important especially if you are upgrading the package to a newer version in which the config file structure has changed. -No worries, if you have customizations in your config file that you would like to keep, your current config file will be backed up to `config/nested-comments.php.bak` before the new config file is published. - -You will also be asked if you would like to re-publish the package's assets. This is also important in case the package's styles and scripts have changed in the new version. - -Adjust the configuration file as necessary, then run migrations. - -`That's it! You are now ready to add nested comments - -## Usage: Comments -At the very basic level, this package is simply a Livewire Component that takes in a model record which is commentable. Follow the following steps to prepare your model to be commentable or reactable: -1. Add the `HasComments` trait to your model -```php - -use Coolsam\NestedComments\Concerns\HasComments; - -class Conference extends Model -{ - use HasComments; - - // ... -} - -``` -2. If you would like to be able to react to your model directly as well, add the `HasReactions` trait to your model -```php -use Coolsam\NestedComments\Concerns\HasReactions; - -class Conference extends Model -{ - use HasReactions; - - // ... -} -``` -3. You can now access the comments and reactions of your model in the following ways - -### Using the Comments Infolist Entry - -```php -public static function infolist(Infolist $infolist): Infolist - { - return $infolist - ->schema([ - Section::make('Basic Details') - ->schema([ - TextEntry::make('name'), - TextEntry::make('start_date') - ->dateTime(), - TextEntry::make('end_date') - ->dateTime(), - TextEntry::make('created_at') - ->dateTime(), - ]), - - // Add the comments entry - \Coolsam\NestedComments\Filament\Infolists\CommentsEntry::make('comments'), - ]); - } -``` -![image](https://github.com/user-attachments/assets/da84b49e-66c7-4453-b5d4-b7b18f204bba) - - - -### Using the Comments Widget inside a Resource Page (e.g EditRecord) - -As long as the resource page interacts with the record, the CommentsWidget will resolve the record automatically. - -```php -class EditConference extends EditRecord -{ - protected static string $resource = ConferenceResource::class; - - protected function getHeaderActions(): array - { - return [ - Actions\ViewAction::make(), - Actions\DeleteAction::make(), - ]; - } - - protected function getFooterWidgets(): array - { - return [ - \Coolsam\NestedComments\Filament\Widgets\CommentsWidget::class, - ]; - } -} -``` -![image](https://github.com/user-attachments/assets/bd56d52d-b791-4f24-a202-b0948574d811) - -### Using the Comments Widget in a custom Filament Page (You have to pass $record manually) - -```php -// NOTE: It's up to you how to get your record, as long as you pass it to the widget -public function getRecord(): ?Conference -{ - return Conference::latest()->first(); -} - -protected function getFooterWidgets(): array -{ - return [ - CommentsWidget::make(['record' => $this->getRecord()]) - ]; -} -``` - -### Using the Comments Page Action in a Resource Page (which interacts with $record) - -```php -namespace App\Filament\Resources\ConferenceResource\Pages; - -use App\Filament\Resources\ConferenceResource; -use Coolsam\NestedComments\Filament\Actions\CommentsAction; -use Filament\Actions; -use Filament\Resources\Pages\ViewRecord; -use Illuminate\Database\Eloquent\Model; - -class ViewConference extends ViewRecord -{ - protected static string $resource = ConferenceResource::class; - - protected function getHeaderActions(): array - { - return [ - CommentsAction::make() - ->badgeColor('danger') - ->badge(fn(Model $record) => $record->getAttribute('comments_count')), - Actions\EditAction::make(), - ]; - } -} -``` -![image](https://github.com/user-attachments/assets/678d3f1e-b3f9-4a77-b263-af5538c72e2b) - -![image](https://github.com/user-attachments/assets/372c6390-ea4e-4d19-8943-784506126cc1) - -### Using the Comments Page Action in a custom Filament Page (You have to pass $record manually) -In this case you will have to pass the record attribute manually. - -```php -protected function getHeaderActions(): array -{ - return [ - CommentsAction::make() - ->record($this->getRecord()) // Define the logic for getting your record e.g in $this->getRecord() - ->badgeColor('danger') - ->badge(fn(Model $record) => $record->getAttribute('comments_count')), - Actions\EditAction::make(), - ]; -} -``` - -### Using the Comments Table Action - -```php -public static function table(Table $table): Table -{ - return $table - ->columns([ - // ... Columns - ]) - ->actions([ - \Coolsam\NestedComments\Filament\Tables\Actions\CommentsAction::make() - ->button() - ->badgeColor('danger') - ->badge(fn(Conference $record) => $record->getAttribute('comments_count')), - // ... Other actions - ]); -} -``` -![image](https://github.com/user-attachments/assets/27eead51-c237-4865-b185-3245629cabe4) - -### Using the Comments Blade Component ANYWHERE! -This unlocks incredible possibilities. It allows you to render your comments even in your own frontend blade page. All you have to do is simply pass the commentable `$record` to the blade component -```php -$record = Conference::find(1); // Get your record from the database then, - - -``` - -Alternatively, you could use the Livewire component if you prefer. -```php -$record = Conference::find(1); // Get your record from the database then, - - -``` - -### Mentions -The package uses Filament TipTap Editor which supports mentions. You can mention users in your comments by typing `@` followed by the user's name. -In the future, the package will support sending notifications to the mentioned users via database notifications if supported. -For more on how to customize the mentions, see the [Package Customization](#customize-how-to-get-the-mention-items) section below. - -![image](https://github.com/user-attachments/assets/bd7a395a-fc32-4057-b6bc-24763132f555) - - -## Usage: Emoji Reactions -This package also allows you to add emoji reactions to your models. You can use the `HasReactions` trait to add reactions to any model. The reactions are stored in a separate table, and you can customize the reactions that are available via the configuration file. -The Comments model that powers the comments feature described above already uses emoji reactions. - -In order to start using reactions for your model, add the `HasReactions` trait to your model. You can then use the `reactions` method to get the reactions for the model. - -```php -use Coolsam\NestedComments\Concerns\HasReactions; - -class Conference extends Model -{ - use HasReactions; - - // ... -} -``` -The above trait adds the `react()` method to your model, allowing you to toggle a reaction for the model. You can also use the `reactions` method to get the reactions for the model. - -```php -$conference = Conference::find(1); -$comference->react('👍'); // React to the conference with a thumbs up emoji -``` -You can also use the `reactions` method to get the reactions for the model. - -```php -$conference = Conference::find(1); -$reactions = $conference->reactions; // Get the reactions for the conference -``` -Other useful methods include -```php -/** -* @var \Illuminate\Database\Eloquent\Model&\Coolsam\NestedComments\Concerns\HasReactions $conference - */ -$conference = Conference::find(1); -$conference->total_reactions; // Get the total number of reactions for the conference -$conference->reactions_counts; // Get the no of reactions for each emoji for the model -$conference->my_reactions; // Get the reactions for the current user -$conference->emoji_reactors // Get the list of users who reacted to the model, grouped by emoji -$conference->isAllowed('👍') // check if the app allows the user to react with the specified emoji -$conference->reactions_map // return the map of all the reactions for the model, grouped by emoji. This tells you the number of reactions for each emoji, and whether the current user has reacted with that emoji +composer test ``` -To interact with the methods above with ease within and even outside Filament, this package comes with the following handy components: -### Reactions Infolist Entry -```php -use Coolsam\NestedComments\Filament\Infolists\ReactionsEntry; +## التثبيت -public static function infolist(Infolist $infolist): Infolist -{ - return $infolist - ->schema([ - Section::make('Basic Details') - ->schema([ - TextEntry::make('name'), - TextEntry::make('start_date') - ->dateTime(), - TextEntry::make('end_date') - ->dateTime(), - TextEntry::make('created_at') - ->dateTime(), - // Add the reactions entry - ReactionsEntry::make('reactions')->columnSpanFull(), - ])->columns(4), - ]); -} +```bash +composer require hadialharbi/nested-comments ``` -![image](https://github.com/user-attachments/assets/06ae7e76-1668-4e92-9a4f-a125f7d94b03) -### Reactions Blade Component -Just include the blade component anywhere in your blade file and pass the model record to it. -```php -$record = Conference::find(1); // Get your record from the database then, -``` -In your view: -```bladehtml - -``` +ثم نفّذ الأمر التالي لتثبيت الحزمة: -### Reactions Livewire Component -Similar to the blade component, you can use the Livewire component anywhere in your Livewire component and pass the model record to it. -```php -$record = Conference::find(1); // Get your record from the database then, -``` -In your view: -```bladehtml - +```bash +php artisan nested-comments:install ``` -The two components can be used anywhere, in resource pages, custom pages, actions, form fields, widgets, livewire components or just plain blade views. Here is a sample screenshot of how the components will be rendered: -![image](https://github.com/user-attachments/assets/0162f294-0477-454c-ae5c-67424edc207f) - -## Package Customization -You can customize the package by changing most of the default values in the config file after publishing it. -Additionally, you can customize how the package interacts with your models by overriding some methods in your commentable model. +واتبع التعليمات لنشر ملفات الإعدادات والمخططات. -### Customize how to get the Comment Author's Name -You can customize how to get the comment author's name by overriding the `getUserName` method in your commentable model. -By default, the package uses the `name` attribute of the user model, but you can change this to any other attribute or method that returns a string. +## الاستخدام -This name will be displayed in the comment card, and it will also be used to mention the user in the comment text. +1. أضف Trait `HasComments` إلى الموديل الذي ترغب بتعليقه عليه. +2. أضف Trait `HasReactions` إذا رغبت بدعم الإيموجي. +3. استخدم المكونات داخل Infolist أو Blade أو Livewire بكل سلاسة. -```php -// e.g in your Post model or any other model that uses the HasComments trait -use Coolsam\NestedComments\Concerns\HasComments; +### Blade: -public function getUserName(Model|Authenticatable|null $user): string -{ - return $user?->getAttribute('username') ?? $user?->getAttribute('guest_name') ?? 'Guest'; -} +```blade + ``` -### Customize the User's Avatar -You can customize the user's avatar by overriding the `getUserAvatar` method in your commentable model. - -By default, the package uses [ui-avatars](https://ui-avatars.com) to generate the avatar based on the user's name, but you can change this to any other method that returns a URL to the user's avatar image. - -```php -// e.g in your Post model or any other model that uses the HasComments trait -use Coolsam\NestedComments\Concerns\HasComments; - -public function getUserAvatar(Model|Authenticatable|string|null $user): ?string -{ -// return 'https://yourprofile.url.png'; - return $user->getAttribute('profile_url') // get your user's profile url here, assuming you have defined it in your user's model. -} -``` - -### Customize how to get the Mention Items -You can customize how to get the mention items by overriding and changing the `getMentionsQuery` method in your commentable model. -By default, the package gets mention items from all users in your database. -For example, if you would only like to mention users who have commented on the current thread, you can do so by changing the method to return only those users. -There is a handy method included in the default class to achieve this. Alternatively, you can go wild and mention fruits instead of users! The choice is within your freedom. - -```php -// e.g in your Post model or any other model that uses the HasComments trait -use Coolsam\NestedComments\Concerns\HasComments; +### Livewire: -public function getMentionsQuery(string $query): Builder -{ - return app(NestedComments::class)->getCurrentThreadUsersQuery($query, $this); -} +```blade + ``` -### Customize the Supported Emoji Reactions -You can customize the supported emoji reactions by changing the `reactions` array in the config file. -Decent defaults are provided, but you can change them to any emojis you prefer. +### ردود الفعل (الإيموجي) -```php -return [ - '👍', - '❤️', - '😂', - '😮', - '😢', - '😡', -]; +```blade + ``` -## Testing - -```bash -composer test -``` - -## Open Source Dependencies - -This package uses the following awesome open source packages, among many others under the hood: - -* [Filament](https://filamentphp.com/) -* [Livewire](https://livewire.laravel.com/) -* [Laravel](https://laravel.com/) -* [AlpineJS](https://alpinejs.dev/) -* [Laravel NestedSet](https://github.com/lazychaser/laravel-nestedset) -* [Filament Tiptap Editor](https://github.com/awcodes/filament-tiptap-editor) - -I am grateful for the work that has been put into these packages. They have made it possible to build this package in a short time. - -## Changelog - -Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. - -## Contributing -Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details. +## التخصيص -## Security Vulnerabilities +يمكنك تعديل ملف الإعدادات `config/nested-comments.php` لتغيير: -Please review [our security policy](../../security/policy) on how to report security vulnerabilities. +* الأشكال والألوان. +* قائمة الإيموجي المسموحة. +* التحكم بالسماح للضيوف بالتفاعل. +* النصوص المعروضة في الواجهات. +* تحديد صلاحيات التعديل والحذف. +* التحكم في تنسيق التاريخ. -## Credits +## الشكر -- [Sam Maosa](https://github.com/coolsam726) -- [All Contributors](../../contributors) +تم بناء هذه الحزمة على العمل الرائع من [coolsam/nested-comments](https://github.com/coolsam726/nested-comments) — شكرًا للمطور سام ماوسا على جهده وتفانيه في بناء أساس قوي لهذه الإضافة. +كما نعبر عن امتناننا لكل من ساهم في تطوير أدوات: -## License +* FilamentPHP +* Laravel +* Livewire +* AlpineJS +* Laravel NestedSet +* Tiptap Editor -The MIT License (MIT). Please see [License File](LICENSE.md) for more information. diff --git a/composer.json b/composer.json index 2f0fcdb..c47bc76 100644 --- a/composer.json +++ b/composer.json @@ -1,57 +1,67 @@ { - "name": "coolsam/nested-comments", - "description": "Add Nested comments/replies to filament forms, infolists and resources", + "name": "hadialharbi/nested-comments", + "description": "Fork of coolsam/nested-comments with Arabic RTL support and Filament integration", "keywords": [ - "coolsam", + "nested-comments", "laravel", - "nested-comments" + "filamentphp", + "livewire", + "rtl", + "arabic", + "comments" ], - "homepage": "https://github.com/coolsam/nested-comments", + "homepage": "https://github.com/hadialharbi2020/nested-comments", "support": { - "issues": "https://github.com/coolsam/nested-comments/issues", - "source": "https://github.com/coolsam/nested-comments" + "issues": "https://github.com/hadialharbi2020/nested-comments/issues", + "source": "https://github.com/hadialharbi2020/nested-comments" }, "license": "MIT", "authors": [ - { - "name": "Sam Maosa", - "email": "maosa.sam@gmail.com", - "role": "Developer" - } - ], + { + "name": "Hadi Al-Harbi", + "email": "hadionline1994@gmail.com", + "role": "Maintainer" + }, + { + "name": "Sam Maosa", + "email": "maosa.sam@gmail.com", + "role": "Original Developer" + } +], "require": { "php": "^8.2", "awcodes/filament-tiptap-editor": "^3.5.12", "filament/filament": "^3.2", - "kalnoy/nestedset": "^6.0.5", + "illuminate/translation": "*", + "kalnoy/nestedset": "^6.0", "spatie/laravel-package-tools": "^1.15.0", "tangodev-it/filament-emoji-picker": "^1.0.3" }, "require-dev": { "barryvdh/laravel-ide-helper": "^3.5", "laravel/pint": "^1.0", + "livewire/livewire": "^3.6", "nunomaduro/larastan": "^3.1.0", - "orchestra/testbench": "^9.12", - "pestphp/pest-plugin-laravel": "^3.1", + "orchestra/testbench": "^10.4", "pestphp/pest-plugin-livewire": "^3.0", "phpstan/extension-installer": "^1.4.3", "spatie/laravel-ray": "^1.39" }, "autoload": { "psr-4": { - "Coolsam\\NestedComments\\": "src/", - "Coolsam\\NestedComments\\Database\\Factories\\": "database/factories/" + "Hadialharbi\\NestedComments\\": "src/", + "Hadialharbi\\NestedComments\\Database\\Factories\\": "database/factories/" } }, "autoload-dev": { "psr-4": { - "Coolsam\\NestedComments\\Tests\\": "tests/" + "Hadialharbi\\NestedComments\\Tests\\": "tests/" } }, "scripts": { "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", "analyse": "vendor/bin/phpstan analyse", - "test": "vendor/bin/pest", + "test": "phpunit", "test-coverage": "vendor/bin/pest --coverage", "format": "vendor/bin/pint" }, @@ -65,10 +75,10 @@ "extra": { "laravel": { "providers": [ - "Coolsam\\NestedComments\\NestedCommentsServiceProvider" + "Hadialharbi\\NestedComments\\NestedCommentsServiceProvider" ], "aliases": { - "NestedComments": "Coolsam\\NestedComments\\Facades\\NestedComments" + "NestedComments": "Hadialharbi\\NestedComments\\Facades\\NestedComments" } } }, diff --git a/config/nested-comments.php b/config/nested-comments.php index 169b35f..9cdd830 100644 --- a/config/nested-comments.php +++ b/config/nested-comments.php @@ -1,56 +1,64 @@ [ 'comments' => 'comments', 'reactions' => 'reactions', - 'users' => 'users', // The table that will be used to get the authenticated user + 'users' => 'users', ], 'models' => [ - 'comment' => \Coolsam\NestedComments\Models\Comment::class, - 'reaction' => \Coolsam\NestedComments\Models\Reaction::class, - 'user' => env('AUTH_MODEL', 'App\Models\User'), // The model that will be used to get the authenticated user + 'comment' => Hadialharbi\NestedComments\Models\Comment::class, + 'reaction' => Hadialharbi\NestedComments\Models\Reaction::class, + 'user' => env('AUTH_MODEL', App\Models\User::class), ], 'policies' => [ 'comment' => null, 'reaction' => null, ], + 'allowed-reactions' => [ - '👍' => 'thumbs up', // thumbs up - '👎' => 'thumbs down', // thumbs down - '❤️' => 'heart', // heart - '😂' => 'laughing', // laughing - '😮' => 'surprised', // surprised - '😢' => 'crying', // crying - '💯' => 'hundred points', // angry - '🔥' => 'fire', // fire - '🎉' => 'party popper', // party popper - '🚀' => 'rocket', // rocket + '👍' => 'thumbs up', + '👎' => 'thumbs down', + '❤️' => 'heart', + '😂' => 'laughing', + '😮' => 'surprised', + '😢' => 'crying', + '💯' => 'hundred points', + '🔥' => 'fire', + '🎉' => 'party popper', + '🚀' => 'rocket', ], - 'allow-all-reactions' => env('ALLOW_ALL_REACTIONS', false), // Allow any other emoji apart from the ones listed above - 'allow-multiple-reactions' => env('ALLOW_MULTIPLE_REACTIONS', false), // Allow multiple reactions from the same user - 'allow-guest-reactions' => env('ALLOW_GUEST_REACTIONS', false), // Allow guest users to react - 'allow-guest-comments' => env('ALLOW_GUEST_COMMENTS', false), // Allow guest users to comment + + 'allow-all-reactions' => env('ALLOW_ALL_REACTIONS', false), + 'allow-multiple-reactions' => env('ALLOW_MULTIPLE_REACTIONS', false), + 'allow-guest-reactions' => env('ALLOW_GUEST_REACTIONS', false), + 'allow-guest-comments' => env('ALLOW_GUEST_COMMENTS', false), 'format-created-date' => 'F j Y h:i:s A', - /* - |-------------------------------------------------------------------------- - | Livewire Component - |-------------------------------------------------------------------------- - | - */ - 'show-heading' => true, + 'show-heading' => true, 'show-badge-counter' => true, 'badge-counter-color' => 'info', 'show-refresh-button' => true, - 'style-refresh-button' => 'button', // 'button' or 'icon', + 'style-refresh-button' => 'button', 'icon-refresh-button' => 'heroicon-m-sparkles', 'outlined-refresh-button' => false, - 'color-refresh-button' => 'info' // 'danger', 'gray', 'info', 'success' or 'warning' + 'color-refresh-button' => 'info', + + // 🆕 إضافات مقترحة مستقبلًا: + 'enable_rtl' => true, + + 'ui' => [ + 'show_user_avatar' => true, + 'show_datetime_tooltip' => true, + ], + + 'permissions' => [ + 'can_edit_comment' => true, + 'can_delete_comment' => true, + ], ]; diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 92d3fa4..57da0bd 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -1,6 +1,6 @@ id(); + $table->nestedSet(); + $table->foreignId('user_id')->nullable()->constrained('users')->cascadeOnDelete(); + $table->text('body'); + $table->morphs('commentable'); + $table->ulid('guest_id')->nullable()->index(); + $table->string('guest_name')->nullable(); + $table->ipAddress()->nullable(); + $table->boolean('is_published')->default(false); + $table->timestamps(); + }); + + Schema::create('reactions', function (Blueprint $table) { + $table->id(); + $table->foreignId('user_id')->nullable()->constrained('users')->cascadeOnDelete(); + $table->morphs('reactable'); + $table->string('emoji'); + $table->ulid('guest_id')->nullable()->index(); + $table->string('guest_name')->nullable(); + $table->ipAddress()->nullable(); + $table->boolean('is_published')->default(false); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('reactions'); + Schema::dropIfExists('comments'); + } +}; diff --git a/fix-namespace.sh b/fix-namespace.sh new file mode 100755 index 0000000..e69de29 diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 10036df..e58c298 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -8,7 +8,7 @@ parameters: - config - database ignoreErrors: - - '#Trait Coolsam\\NestedComments\\Concerns\\HasComments is used zero times and is not analysed#' + - '#Trait Hadialharbi\\NestedComments\\Concerns\\HasComments is used zero times and is not analysed#' - message: "#Called 'env' outside of the config directory which returns null when the config is cached, use 'config'#" path: config/* diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6a90da5..23bb874 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,7 +16,7 @@ backupStaticProperties="false" > - + tests diff --git a/resources/css/index.css b/resources/css/index.css index cb93d99..785c302 100644 --- a/resources/css/index.css +++ b/resources/css/index.css @@ -1,6 +1,13 @@ @import '../../vendor/filament/filament/resources/css/theme.css'; @import '../../vendor/awcodes/filament-tiptap-editor/resources/css/plugin.css'; -.comment-mention, [data-mention-id] { - @apply bg-primary-50 !text-primary-500 dark:bg-gray-700 dark:text-primary-50 dark:border-primary-500 p-1 rounded-full px-2 before:content-["@"]; -} \ No newline at end of file +.comment-mention:dir(rtl), +[data-mention-id]:dir(rtl) { + @apply rounded-full p-1 px-2 text-primary-500 bg-primary-50 dark:bg-gray-700 dark:text-primary-50 dark:border-primary-500; + direction: rtl; +} + +.comment-mention:dir(rtl)::before, +[data-mention-id]:dir(rtl)::before { + content: "@"; /* أو "@" بالعربي إذا حبيت */ +} diff --git a/resources/lang/ar/nested-comments.php b/resources/lang/ar/nested-comments.php new file mode 100644 index 0000000..a97099b --- /dev/null +++ b/resources/lang/ar/nested-comments.php @@ -0,0 +1,68 @@ + [ + 'general' => [ + 'guest' => 'زائر', + 'no_comments_provided' => 'لا توجد تعليقات.', + 'no_commentable_record_set' => 'لم يتم تعيين سجل قابل للتعليق.', + 'record_is_not_configured_for_reactions' => 'السجل الحالي غير مهيأ للتفاعلات. يرجى تضمين الـ Trait المسمى `HasReactions` في النموذج.', + 'no_commentable_record_found_widget' => 'لم يتم العثور على سجل قابل للتعليق. يرجى تمرير سجل إلى الودجت.', + 'reply' => 'رد', + 'no_replies' => 'لا توجد ردود بعد.', + 'comments' => 'التعليقات', + ], + 'form' => [ + 'field' => [ + 'comment' => [ + 'label' => 'تعليقك', + 'mention_items_placeholder' => 'ابحث عن المستخدمين بالاسم أو البريد الإلكتروني', + 'empty_mention_items_message' => 'لم يتم العثور على مستخدمين', + ], + ], + 'buttons' => [ + 'submit' => 'إرسال', + 'cancel' => 'إلغاء', + 'add_comment' => 'إضافة تعليق جديد', + 'add_reply' => 'إضافة رد', + 'reply' => 'رد', + 'hide_replies' => 'إخفاء الردود', + 'refresh' => 'تحديث', + ], + ], + 'table' => [ + 'actions' => [ + 'view_comments' => [ + // 'label' => 'عرض التعليق', + 'heading' => 'التعليقات', + 'close' => 'إغلاق', + ], + ], + ], + 'actions' => [ + 'view_comment' => [ + // 'label' => 'عرض التعليق', + 'heading' => 'عرض التعليقات', + 'close' => 'إغلاق', + ], + ], + ], + 'reactions' => [ + 'add_reaction' => 'أضف تفاعلًا', + + // يمكنك ترجمة الرموز التعبيرية (emoji) أيضًا إن رغبت + + '👍' => 'إعجاب', + '👎' => 'عدم إعجاب', + '❤️' => 'إعجاب قوي', + '😂' => 'مضحك', + '😮' => 'مندهش', + '😢' => 'محزن', + '💯' => 'ممتاز', + '🔥' => 'ناري', + '🎉' => 'احتفال', + '🚀' => 'إطلاق', + ], + +]; diff --git a/resources/lang/en/nested-comments.php b/resources/lang/en/nested-comments.php index dc9872a..09516e2 100644 --- a/resources/lang/en/nested-comments.php +++ b/resources/lang/en/nested-comments.php @@ -1,6 +1,6 @@ [ 'general' => [ @@ -30,27 +30,27 @@ 'reply' => 'Reply', 'hide_replies' => 'Hide Replies', 'refresh' => 'Refresh', - ] + ], ], 'table' => [ 'actions' => [ 'view_comments' => [ - //'label' => 'View comment', + // 'label' => 'View comment', 'heading' => 'Comments', - 'close' => 'Close' - ] + 'close' => 'Close', + ], ], ], 'actions' => [ 'view_comment' => [ - //'label' => 'View comment', + // 'label' => 'View comment', 'heading' => 'View Comments', - 'close' => 'Close' - ] - ] + 'close' => 'Close', + ], + ], ], 'reactions' => [ 'add_reaction' => 'Add a reaction', - ] + ], ]; diff --git a/resources/lang/fr/nested-comments.php b/resources/lang/fr/nested-comments.php index 493d193..487d552 100644 --- a/resources/lang/fr/nested-comments.php +++ b/resources/lang/fr/nested-comments.php @@ -1,6 +1,6 @@ [ 'general' => [ @@ -17,7 +17,7 @@ 'field' => [ 'comment' => [ 'label' => '', - //'label' => 'Votre Commentaire', + // 'label' => 'Votre Commentaire', 'mention_items_placeholder' => 'Rechercher les utilisateurs par nom ou email', 'empty_mention_items_message' => 'Aucun utilisateur trouvé', @@ -31,25 +31,25 @@ 'reply' => 'Répondre', 'hide_replies' => 'Cacher les réponses', 'refresh' => 'Rafraîchir', - ] + ], ], 'table' => [ 'actions' => [ 'view_comments' => [ 'heading' => 'Commentaires', - 'close' => 'Fermer' - ] + 'close' => 'Fermer', + ], ], ], 'actions' => [ 'view_comment' => [ 'heading' => 'Voir les Commentaires', - 'close' => 'Fermer' - ] - ] + 'close' => 'Fermer', + ], + ], ], 'reactions' => [ 'add_reaction' => 'Ajouter une réaction', - ] + ], ]; diff --git a/resources/views/components/reactions.blade.php b/resources/views/components/reactions.blade.php index a6d1780..b66562a 100644 --- a/resources/views/components/reactions.blade.php +++ b/resources/views/components/reactions.blade.php @@ -2,7 +2,7 @@ 'record' ]) @if(isset($record)) - @if(app(\Coolsam\NestedComments\NestedComments::class)->classHasTrait($record, \Coolsam\NestedComments\Concerns\HasReactions::class)) + @if(app(\Hadialharbi\NestedComments\NestedComments::class)->classHasTrait($record, \Hadialharbi\NestedComments\Concerns\HasReactions::class)) @else

{{ __('nested-comments::nested-comments.comments.general.record_is_not_configured_for_reactions') }}

diff --git a/resources/views/livewire/add-comment.blade.php b/resources/views/livewire/add-comment.blade.php index a7e9936..0f5c7d2 100644 --- a/resources/views/livewire/add-comment.blade.php +++ b/resources/views/livewire/add-comment.blade.php @@ -1,25 +1,20 @@
@if($this->addingComment) -
- {{ $this->form }} - - {{ __('nested-comments::nested-comments.comments.form.buttons.submit') }} - - - {{ __('nested-comments::nested-comments.comments.form.buttons.cancel') }} - -
+
+ {{ $this->form }} + + {{ __('nested-comments::nested-comments.comments.form.buttons.submit') }} + + + {{ __('nested-comments::nested-comments.comments.form.buttons.cancel') }} + +
@else - - - + + + @endif -
+ \ No newline at end of file diff --git a/resources/views/livewire/comment-card.blade.php b/resources/views/livewire/comment-card.blade.php index cd4675a..3943b1d 100644 --- a/resources/views/livewire/comment-card.blade.php +++ b/resources/views/livewire/comment-card.blade.php @@ -1,40 +1,39 @@
-
-
-
- -
+
+
+
+ +

{{ $this->getCommentator() }}

-

+

{{ $this->comment->created_at?->diffForHumans() }}

-

{{ $this->comment->created_at->format(config('nested-comments.format-created-date', 'F j Y h:i:s A')) }}

+

+ {{ $this->comment->created_at->format( + config( + 'nested-comments.format-created-date', + 'F j Y h:i:s + A', + ), + ) }} +

-
+
{!! e(new \Illuminate\Support\HtmlString($this->comment?->body)) !!}
-
- - @if($this->comment->replies_count > 0) +
+ + @if ($this->comment->replies_count > 0) - {{\Illuminate\Support\Number::forHumans($this->comment->replies_count, maxPrecision: 3, abbreviate: true)}} {{ str(__('nested-comments::nested-comments.comments.general.reply'))->plural($this->comment->replies_count) }} + {{ \Illuminate\Support\Number::forHumans($this->comment->replies_count, maxPrecision: 3, abbreviate: true) }} + {{ str(__('nested-comments::nested-comments.comments.general.reply'))->plural($this->comment->replies_count) }} @else @@ -42,41 +41,42 @@ class="cursor-pointer" @endif - +
- @if($showReplies) -
- @foreach($this->comment->children as $reply) - + @if ($replyingToCommentId === $comment->id) +
+ + {{-- فقط ردود هذا التعليق يتم عرضها --}} + @foreach ($this->comment->children as $reply) + @endforeach - + + {{-- حقل الرد --}} + + + {{-- زر إخفاء --}} + x-on:click=" + if ($refs.repliesContainer && $refs.repliesContainer.offsetHeight && $refs.repliesContainer.style.display !== 'none') { + const offset = $refs.repliesContainer.offsetHeight; + window.scrollBy({ top: -offset, behavior: 'smooth' }); + } + " + type="button" label="{{ __('nested-comments::nested-comments.comments.form.buttons.hide_replies') }}" + tooltip="{{ __('nested-comments::nested-comments.comments.form.buttons.hide_replies') }}" + icon="heroicon-o-minus-circle" class="absolute -left-8 -bottom-4" wire:click.prevent="toggleReplies" />
@endif +
@script - + @endscript diff --git a/resources/views/livewire/comments.blade.php b/resources/views/livewire/comments.blade.php index b9279ac..abaf305 100644 --- a/resources/views/livewire/comments.blade.php +++ b/resources/views/livewire/comments.blade.php @@ -1,40 +1,37 @@ @if(config('nested-comments.show-heading', true)) - -
-
- {{ __('nested-comments::nested-comments.comments.general.comments') }} -
- @if(config('nested-comments.show-badge-counter', true)) -
- - {{\Illuminate\Support\Number::forHumans($this->comments->count(),maxPrecision: 3, abbreviate: true)}} - -
- @endif + +
+
+ {{ __('nested-comments::nested-comments.comments.general.comments') }}
- + @if(config('nested-comments.show-badge-counter', true)) +
+ + {{\Illuminate\Support\Number::forHumans($this->comments->count(),maxPrecision: 3, abbreviate: + true)}} + +
+ @endif +
+
@endif @if(config('nested-comments.show-refresh-button', true)) - - - @if(config('nested-comments.style-refresh-button', 'button') === 'button') - {{ __('nested-comments::nested-comments.comments.form.buttons.refresh') }} - @endif - - + + + @if(config('nested-comments.style-refresh-button', 'button') === 'button') + {{ __('nested-comments::nested-comments.comments.form.buttons.refresh') }} + @endif + + @endif @foreach($this->comments as $comment) - + @endforeach - + \ No newline at end of file diff --git a/resources/views/livewire/reaction-panel.blade.php b/resources/views/livewire/reaction-panel.blade.php index a33d37a..6ac2e2c 100644 --- a/resources/views/livewire/reaction-panel.blade.php +++ b/resources/views/livewire/reaction-panel.blade.php @@ -1,43 +1,37 @@ -
- @foreach($this->record->reactions_map->filter(fn($reaction) => collect($reaction)->get('reactions') > 0) as $reaction => $attribs) - true, - ]) - title="{{$reaction}} {{collect($attribs)->get('reactions')}} {{str(collect($attribs)->get('name'))->plural(collect($attribs)->get('reactions'))}}" - tooltip="{{$reaction}} {{collect($attribs)->get('reactions')}} {{str(collect($attribs)->get('name'))->plural(collect($attribs)->get('reactions'))}}" - :outlined="true" - :color="collect($attribs)->get('meToo') ? 'primary' : 'gray'" size="xs" - > - {{$reaction}} {{\Illuminate\Support\Number::forHumans(collect($attribs)->get('reactions'), maxPrecision: 2)}} - +
+ @foreach($this->record->reactions_map->filter(fn($reaction) => collect($reaction)->get('reactions') > 0) as $reaction => $attribs) + + {{ $reaction }} {{ \Illuminate\Support\Number::forHumans(collect($attribs)->get('reactions'), + maxPrecision: 2) }} + @endforeach - + + stroke="currentColor" class="size-4"> + d="M15.182 15.182a4.5 4.5 0 0 1-6.364 0M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0ZM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Z" /> -
+
@foreach($this->record->reactions_map as $reaction => $attribs) - true, - ]) - :outlined="true" - :color="collect($attribs)->get('meToo') ? 'primary' : 'gray'" - size="md" - title="{{collect($attribs)->get('name')}}" + true, + ]) + :outlined="true" + :color="collect($attribs)->get('meToo') ? 'primary' : 'gray'" + size="md" + title="{{collect($attribs)->get('name')}}" > - {{$reaction}} - + {{$reaction}} + @endforeach -
- -
+
+ +
\ No newline at end of file diff --git a/scripts/check-package-readiness.php b/scripts/check-package-readiness.php new file mode 100755 index 0000000..25ee0ae --- /dev/null +++ b/scripts/check-package-readiness.php @@ -0,0 +1,63 @@ +#!/usr/bin/env php + class_exists(\Livewire\Livewire::class)); + +check('NestedCommentsServiceProvider is autoloadable', function () { + return class_exists(\Hadialharbi\NestedComments\NestedCommentsServiceProvider::class); +}); + +check('comments.blade.php view exists', fn () => file_exists(__DIR__ . '/../resources/views/livewire/comments.blade.php')); + +check('Lang files exist', fn () => is_dir(__DIR__ . '/../resources/lang/ar')); + +check('Config file exists', fn () => file_exists(__DIR__ . '/../config/nested-comments.php')); + +check('composer.json autoload is correct', function () { + $composer = json_decode(file_get_contents(__DIR__ . '/../composer.json'), true); + + return isset($composer['autoload']['psr-4']['Hadialharbi\\NestedComments\\']); +}); + +check('Packagist name is updated', function () { + $composer = json_decode(file_get_contents(__DIR__ . '/../composer.json'), true); + + return $composer['name'] === 'hadialharbi/nested-comments'; +}); + +echo "\n"; + +if (empty($errors)) { + echo "🎉 Package is READY to be tagged and pushed to Packagist.\n"; + exit(0); +} else { + echo "⚠️ Please fix the following before publishing:\n"; + foreach ($errors as $e) { + echo " - $e\n"; + } + exit(1); +} diff --git a/setup-tests.sh b/setup-tests.sh new file mode 100755 index 0000000..13856fe --- /dev/null +++ b/setup-tests.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +echo "🚀 إنشاء ملفات الاختبارات لحزمة NestedComments..." + +BASE_DIR=$(pwd) + +# إنشاء مجلدات +mkdir -p "$BASE_DIR/tests/Feature" + +# ملف TestCase.php +cat > "$BASE_DIR/tests/TestCase.php" << 'EOF' +set('database.default', 'testing'); + $app['config']->set('database.connections.testing', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + 'prefix' => '', + ]); + } + + protected function defineDatabaseMigrations() + { + $this->loadMigrationsFrom(__DIR__ . '/../database/migrations'); + } +} +EOF + +# ملف CommentTest.php +cat > "$BASE_DIR/tests/Feature/CommentTest.php" << 'EOF' + 'App\\Models\\Post', + 'commentable_id' => 1, + 'user_id' => 1, + 'content' => 'تعليق تجريبي', + ]); + + $this->assertDatabaseHas('comments', [ + 'content' => 'تعليق تجريبي', + ]); + } +} +EOF + +# ملف phpunit.xml +cat > "$BASE_DIR/phpunit.xml" << 'EOF' + + + + + ./tests + + + +EOF + +echo "✅ تم إنشاء ملفات الاختبارات بنجاح!" diff --git a/src/Commands/NestedCommentsCommand.php b/src/Commands/NestedCommentsCommand.php index fe67b35..372cc47 100644 --- a/src/Commands/NestedCommentsCommand.php +++ b/src/Commands/NestedCommentsCommand.php @@ -1,6 +1,6 @@ 'refreshReplies', ]; @@ -31,6 +37,8 @@ public function mount(?Comment $comment = null): void } $this->comment = $comment; + $this->editedBody = $comment->body; + } public function render() @@ -47,7 +55,7 @@ public function refreshReplies(): void public function toggleReplies(): void { - $this->showReplies = ! $this->showReplies; + $this->replyingToCommentId = ($this->replyingToCommentId === $this->comment->id) ? null : $this->comment->id; } public function getAvatar() @@ -73,4 +81,39 @@ public function getCommentator(): string */ return $this->comment->commentable?->getUserNameUsing($this->comment); } + + public function updateComment(): void + { + if (! auth()->check() || auth()->id() !== $this->comment->user_id) { + abort(403); + } + + $this->validate([ + 'editedBody' => 'required|string|min:1', + ]); + + $this->comment->update(['body' => $this->editedBody]); + $this->isEditing = false; + } + + public function deleteComment(): void + { + if (! auth()->check() || auth()->id() !== $this->comment->user_id) { + abort(403); + } + + $this->comment->delete(); + $this->dispatch('refresh')->to(Comments::class); + } + + public function enableEditing(): void + { + $this->isEditing = true; + } + + public function cancelEditing(): void + { + $this->isEditing = false; + $this->editedBody = $this->comment->body; + } } diff --git a/src/Livewire/Comments.php b/src/Livewire/Comments.php index e67dd33..f3bc2c4 100644 --- a/src/Livewire/Comments.php +++ b/src/Livewire/Comments.php @@ -1,11 +1,11 @@ deleteDirectory(public_path('css/coolsam/nested-comments')); - $filesystem->deleteDirectory(public_path('js/coolsam/nested-comments')); + $filesystem->deleteDirectory(public_path('css/hadialharbi/nested-comments')); + $filesystem->deleteDirectory(public_path('js/hadialharbi/nested-comments')); Artisan::call('filament:assets'); } }) @@ -72,7 +72,7 @@ public function configurePackage(Package $package): void ->publishAssets() ->publishMigrations() ->askToRunMigrations() - ->askToStarRepoOnGitHub('coolsam/nested-comments'); + ->askToStarRepoOnGitHub('hadialharbi/nested-comments'); }); $configFileName = $package->shortName(); @@ -140,7 +140,7 @@ public function packageBooted(): void protected function getAssetPackageName(): ?string { - return 'coolsam/nested-comments'; + return 'hadialharbi/nested-comments'; } /** @@ -216,15 +216,19 @@ protected function registerPolicies(): void } } - protected function registerLivewireComponents() + protected function registerLivewireComponents(): void { - $namespace = static::$viewNamespace; - $components = $this->getLivewireComponents(); - if (empty($components)) { + if (! class_exists(\Livewire\Livewire::class)) { return; } + + $namespace = static::$viewNamespace; + $components = $this->getLivewireComponents(); + foreach ($components as $name => $component) { - Livewire::component("$namespace::$name", $component); + // if (class_exists($component)) { + \Livewire\Livewire::component("$namespace::$name", $component); + // } } } diff --git a/src/Testing/TestsNestedComments.php b/src/Testing/TestsNestedComments.php index de4d0a6..d010d38 100644 --- a/src/Testing/TestsNestedComments.php +++ b/src/Testing/TestsNestedComments.php @@ -1,6 +1,6 @@ expect(['dd', 'dump', 'ray']) - ->each->not->toBeUsed(); diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php deleted file mode 100644 index 5d36321..0000000 --- a/tests/ExampleTest.php +++ /dev/null @@ -1,5 +0,0 @@ -toBeTrue(); -}); diff --git a/tests/Feature/CommentTest.php b/tests/Feature/CommentTest.php new file mode 100644 index 0000000..22672b1 --- /dev/null +++ b/tests/Feature/CommentTest.php @@ -0,0 +1,57 @@ +id(); + }); + } + + \App\Models\Post::create(); // منشور وهمي + } + + /** @test */ + public function it_can_create_a_comment() + { + // إنشاء تعليق + $comment = Comment::create([ + 'commentable_type' => \App\Models\Post::class, + 'commentable_id' => 1, + 'body' => 'هذا تعليق تجريبي', + 'user_id' => 1, + ]); + + // التحقق من وجود التعليق في قاعدة البيانات + $this->assertDatabaseHas('comments', [ + 'body' => 'هذا تعليق تجريبي', + 'user_id' => 1, + 'commentable_type' => \App\Models\Post::class, + 'commentable_id' => 1, + ]); + } +} diff --git a/tests/Pest.php b/tests/Pest.php deleted file mode 100644 index ae4ea3b..0000000 --- a/tests/Pest.php +++ /dev/null @@ -1,5 +0,0 @@ -in(__DIR__); diff --git a/tests/TestCase.php b/tests/TestCase.php index 715bbb7..29ded59 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,60 +1,55 @@ 'Coolsam\\NestedComments\\Database\\Factories\\' . class_basename($modelName) . 'Factory' - ); + // 👇 هذا هو المهم لتفعيل المايغريشن + $this->loadMigrationsFrom(__DIR__ . '/../database/migrations'); + + // لو عندك جدول users ضروري تنشئه هنا مؤقتًا: + Schema::create('users', function (Blueprint $table) { + $table->id(); + $table->string('name'); + $table->string('email')->nullable(); + $table->timestamps(); + }); } - protected function getPackageProviders($app) + protected function getPackageProviders($app): array { return [ - ActionsServiceProvider::class, - BladeCaptureDirectiveServiceProvider::class, - BladeHeroiconsServiceProvider::class, - BladeIconsServiceProvider::class, - FilamentServiceProvider::class, - FormsServiceProvider::class, - InfolistsServiceProvider::class, - LivewireServiceProvider::class, - NotificationsServiceProvider::class, - SupportServiceProvider::class, - TablesServiceProvider::class, - WidgetsServiceProvider::class, + LivewireServiceProvider::class, // ✅ أضف هذه السطر + \Illuminate\Translation\TranslationServiceProvider::class, NestedCommentsServiceProvider::class, + NestedSetServiceProvider::class, // أضف هذا السطر ]; } - public function getEnvironmentSetUp($app) + protected function defineEnvironment($app) { - config()->set('database.default', 'testing'); - /* - $migration = include __DIR__.'/../database/migrations/create_nested-comments_table.php.stub'; - $migration->up(); - */ + $app['config']->set('app.locale', 'ar'); + $app['config']->set('app.fallback_locale', 'en'); + $app['config']->set('database.default', 'testing'); + $app['config']->set('database.connections.testing', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + 'prefix' => '', + ]); + + // 👇 لو عندك config خاص بالحزمة + $app['config']->set('nested-comments.tables.users', 'users'); } }