diff --git a/packages/data-languages/.github/FUNDING.yml b/packages/data-languages/.github/FUNDING.yml new file mode 100644 index 000000000..0446fa42d --- /dev/null +++ b/packages/data-languages/.github/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: [mooxphp] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/packages/data-languages/.gitignore b/packages/data-languages/.gitignore new file mode 100644 index 000000000..f397794a6 --- /dev/null +++ b/packages/data-languages/.gitignore @@ -0,0 +1,50 @@ +# Environment +.env +.env.backup + +# Composer +/vendor +composer.lock +auth.json + +# NPM / Node +/node_modules +npm-debug.log +package-lock.json + +# Laravel +/public/hot +/public/storage +/storage/*.key + +# PHPUnit +.phpunit.result.cache +phpunit.xml + +# Yarn +yarn-error.log + +# PHPStan +/build +phpstan.neon + +# Testbench +testbench.yaml +/workbench/* + +# PHP CS Fixer +.php-cs-fixer.cache + +# Homestead +Homestead.json +Homestead.yaml + +# IDEs +/.idea +/.vscode + +# MacOS +.DS_Store + +# Windows +Thumbs.db diff --git a/packages/data-languages/CHANGELOG.md b/packages/data-languages/CHANGELOG.md new file mode 100644 index 000000000..573c399d8 --- /dev/null +++ b/packages/data-languages/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +We currently don't track changes in this package. Please refer to the [Moox Monorepo](https://github.com/mooxphp/moox) for the latest changes. + +We'll add a changelog in the future. diff --git a/packages/data-languages/LICENSE.md b/packages/data-languages/LICENSE.md new file mode 100644 index 000000000..7dfc5ad0b --- /dev/null +++ b/packages/data-languages/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Moox + +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/packages/data-languages/README.md b/packages/data-languages/README.md new file mode 100644 index 000000000..c2d423b69 --- /dev/null +++ b/packages/data-languages/README.md @@ -0,0 +1,227 @@ +![Moox DataLanguages](https://github.com/mooxphp/moox/raw/main/art/banner/data-languages-package.jpg) + +# Moox Data Languages + +This is my package data-languages + +## Quick Installation + +These two commmands are all you need to install the package: + +```bash +composer require moox/data-languages +php artisan data-languages:install +``` + +Curious what the install command does? See manual installation below. + +## What it does + + + +This Laravel Package Template can be used to create a package including a powerful Filament resource called Item. + +![Moox Builder Item](https://github.com/mooxphp/moox/raw/main/art/screenshot/builder-item.jpg) + +Name and table for the Resource can be changed while building your package. + +### Using the Template + +1. Go to https://github.com/mooxphp/data-languages +2. Press the `Use this template` button +3. Create a new repository based on the template +4. Clone the repository locally +5. Run `php build.php`in the repo's directory and follow the steps + - Author Name (Default: Moox Developer): Your Name + - Author Email (Default: dev@moox.org): your@mail.com + - Package Name (Default: Blog Package): Your Package + - Package Description (Default: This is my package Blog Package) + - Package Entity (Default: Item): e.g. Post + - Tablename (Default: items): e.g. posts + +After building the package, you can push the changes to GitHub and create an installable package on Packagist.org. Don't forget to adjust the README to your composer namespace. + +### Config + +After that the Resource is highly configurable. + +#### Tabs and Translation + +Moox Core features like Dynamic Tabs and Translatable Config. See the config file for more details, but as a quick example: + +```php + /* + |-------------------------------------------------------------------------- + | Tabs + |-------------------------------------------------------------------------- + | + | Define the tabs for the Resource table. They are optional, but + | pretty awesome to filter the table by certain values. + | You may simply do a 'tabs' => [], to disable them. + | + */ + + 'tabs' => [ + 'all' => [ + 'label' => 'trans//core::core.all', + 'icon' => 'gmdi-filter-list', + 'query' => [ + [ + 'field' => 'deleted_at', + 'operator' => '=', + 'value' => null, + ], + ], + ], + 'published' => [ + 'label' => 'trans//core::core.published', + 'icon' => 'gmdi-check-circle', + 'query' => [ + [ + 'field' => 'publish_at', + 'operator' => '<=', + 'value' => function () { + return now(); + }, + ], + [ + 'field' => 'deleted_at', + 'operator' => '=', + 'value' => null, + ], + ], + ], + 'scheduled' => [ + 'label' => 'trans//core::core.scheduled', + 'icon' => 'gmdi-schedule', + 'query' => [ + [ + 'field' => 'publish_at', + 'operator' => '>', + 'value' => function () { + return now(); + }, + ], + [ + 'field' => 'deleted_at', + 'operator' => '=', + 'value' => null, + ], + ], + ], + 'draft' => [ + 'label' => 'trans//core::core.draft', + 'icon' => 'gmdi-text-snippet', + 'query' => [ + [ + 'field' => 'publish_at', + 'operator' => '=', + 'value' => null, + ], + [ + 'field' => 'deleted_at', + 'operator' => '=', + 'value' => null, + ], + ], + ], + 'deleted' => [ + 'label' => 'trans//core::core.deleted', + 'icon' => 'gmdi-delete', + 'query' => [ + [ + 'field' => 'deleted_at', + 'operator' => '!=', + 'value' => null, + ], + ], + ], + ], + ], +``` + +All options for Tabs are explained in [Moox Core docs](https://github.com/mooxphp/core/blob/main/README.md#dynamic-tabs). + +#### Item Types + +The item also support 'item' types, means you are able to configure selectable types for your Entity. By default, we provide "Post" and "Page" as example. If you don't want to use types, just empty the array and the field and column become invisible. + +```php + /* + |-------------------------------------------------------------------------- + | Item Types + |-------------------------------------------------------------------------- + | + | This array contains the types of items entities. You can delete + | the types you don't need and add new ones. If you don't need + | types, you can empty this array like this: 'types' => [], + | + */ + + 'types' => [ + 'post' => 'Post', + 'page' => 'Page', + ], +``` + +#### Author Model + +You can configure the user model used for displaying Authors. By default it is tied to App User: + +```php + /* + |-------------------------------------------------------------------------- + | Author Model + |-------------------------------------------------------------------------- + | + | This sets the user model that can be used as author. It should be an + | authenticatable model and support the morph relationship. + | It should have fields similar to Moox User or WpUser. + | + */ + + 'author_model' => \App\Models\User::class, +``` + +You may probably use Moox User + +```php + 'author_model' => \Moox\User\Models\User::class, +``` + +or Moox Press User instead: + +```php + 'author_model' => \Moox\Press\Models\WpUser::class, +``` + + + +## Manual Installation + +Instead of using the install-command `php artisan data-languages:install` you are able to install this package manually step by step: + +```bash +// Publish and run the migrations: +php artisan vendor:publish --tag="data-languages-migrations" +php artisan migrate + +// Publish the config file with: +php artisan vendor:publish --tag="data-languages-config" +``` + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. + +## Security Vulnerabilities + +Please review [our security policy](https://github.com/mooxphp/moox/security/policy) on how to report security vulnerabilities. + +## Credits + +- [All Contributors](../../contributors) + +## License + +The MIT License (MIT). Please see [License File](LICENSE.md) for more information. diff --git a/packages/data-languages/SECURITY.md b/packages/data-languages/SECURITY.md new file mode 100644 index 000000000..43d3d8231 --- /dev/null +++ b/packages/data-languages/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +We maintain the current version of `Moox Data Languages` actively. + +Do not expect security fixes for older versions. + +## Reporting a Vulnerability + +If you find any security-related bug, please report it to security@moox.org. + +Please do not use Github issues, to give us enough time to review and fix the issue, before others can use it, to do stupid things. diff --git a/packages/data-languages/composer.json b/packages/data-languages/composer.json new file mode 100644 index 000000000..85762eb95 --- /dev/null +++ b/packages/data-languages/composer.json @@ -0,0 +1,78 @@ +{ + "name": "moox/data-languages", + "description": "This is my package data-languages", + "keywords": [ + "Laravel", + "Filament", + "Filament plugin", + "Laravel package" + ], + "homepage": "https://moox.org/", + "license": "MIT", + "authors": [ + { + "name": "Moox Developer", + "email": "dev@moox.org", + "role": "Developer" + } + ], + "require": { + "moox/core": "*" + }, + "autoload": { + "psr-4": { + "Moox\\DataLanguages\\": "src", + "Moox\\DataLanguages\\Database\\Factories\\": "database/factories" + } + }, + "extra": { + "laravel": { + "providers": [ + "Moox\\DataLanguages\\DataLanguagesServiceProvider" + ] + } + }, + "minimum-stability": "stable", + "prefer-stable": true, + "require-dev": { + "orchestra/testbench": "^9.5", + "pestphp/pest": "^3.2", + "pestphp/pest-plugin-livewire": "^3.0", + "pestphp/pest-plugin-laravel": "^3.0", + "ryangjchandler/blade-capture-directive": "^1.0" + }, + "autoload-dev": { + "psr-4": { + "Moox\\DataLanguages\\Tests\\": "tests", + "Moox\\DataLanguages\\Database\\Factories\\": "database/factories", + "Workbench\\App\\": "workbench/app/", + "Workbench\\Database\\Factories\\": "workbench/database/factories/", + "Workbench\\Database\\Seeders\\": "workbench/database/seeders/" + } + }, + "scripts": { + "post-autoload-dump": [ + "@clear", + "@prepare" + ], + "clear": "@php vendor/bin/testbench package:purge-data-languages --ansi", + "prepare": "@php vendor/bin/testbench package:discover --ansi", + "build": "@php vendor/bin/testbench workbench:build --ansi", + "serve": [ + "Composer\\Config::disableProcessTimeout", + "@build", + "@php vendor/bin/testbench serve --ansi" + ], + "lint": [ + "@php vendor/bin/phpstan analyse --verbose --ansi" + ], + "test": [ + "@php vendor/bin/phpunit" + ] + }, + "config": { + "allow-plugins": { + "pestphp/pest-plugin": true + } + } +} diff --git a/packages/data-languages/config/data-languages.php b/packages/data-languages/config/data-languages.php new file mode 100644 index 000000000..9a5ffbf02 --- /dev/null +++ b/packages/data-languages/config/data-languages.php @@ -0,0 +1,18 @@ +art(); + $this->welcome(); + $this->publishConfiguration(); + $this->publishMigrations(); + $this->runMigrations(); + $this->registerPluginInPanelProvider(); + $this->sayGoodbye(); + } + + public function art(): void + { + info(' + + ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓ + ▓▓▒░░▒▓▓▒▒░░░░░░▒▒▓▓▓▒░░░░░░░▒▓▓ ▓▓▓▓▒░░░░░░░▒▓▓▓▓ ▓▓▓▓▓▒░░░░░░░▒▒▓▓▓▓▓▒▒▒▒▓▓ ▓▓▓▒▒▒▒▓▓ + ▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▒░░░░░░░░░░░░░▒▓▓▓ ▓▓▓▓▒░░░░░░░░░░░░░▒▓▓▓░░░░░▒▓▓ ▓▓▒░░░░░▓▓ + ▓▒░░░░░░▒▓▓▓▓▒░░░░░░░▒▓▓▓▓░░░░░▒▓▓▓░░░░░▒▓▓▓▓▒░░░░░░░▓▓▓▓░░░░░░▒▓▓▓▓▓░░░░░░▒▓▓░░░░░▒▓▓▓▓▓░░░░░▒▓▓ + ▓▒░░░░▓▓▓▓ ▓▓░░░░░▓▓▓ ▓▓▓░░░░▒▓▓░░░░▒▓▓▓ ▓▓▓▓░░░░░▓░░░░░░▓▓▓▓ ▓▓▓▒░░░░▓▓▓▒░░░░░▓▓▓░░░░░▓▓▓ + ▓▒░░░░▒▓ ▓▓░░░░░▓▓ ▓▓░░░░▒▓░░░░▒▓▓ ▓▓▓░░▒░░░░░▓▓▓ ▓▓░░░░▒▓▓▓▓░░░░░░░░░░░▓▓ + ▓▒░░░░▒▓ ▓▓░░░░░▓▓ ▓▓░░░░▒▓░░░░▒▓ ▓▓▓░░░░░▒▓▓ ▓▓▒░░░░▓ ▓▓▓░░░░░░░░░▓▓ + ▓▒░░░░▒▓ ▓▓░░░░░▓▓ ▓▓░░░░▒▓░░░░▒▓▓ ▓▓▒░░░░░▒░░▒▓▓ ▓▓░░░░▒▓▓▓▒░░░░░▒░░░░░▒▓ + ▓▒░░░░▒▓ ▓▓░░░░░▓▓ ▓▓░░░░▒▓▓░░░░▒▓▓▓ ▓▓▓▒░░░░░▒▒░░░░░▒▓▓▓ ▓▓▓░░░░░▓▓▓░░░░░▒▓▓▓░░░░░▒▓▓ + ▓▒░░░░▒▓ ▓▓░░░░░▓▓ ▓▓░░░░▒▓▓▓░░░░░░▒▒▓▓▒░░░░░░▒▓▓▓▓░░░░░░░▒▒▓▓▒░░░░░░▓▓▓░░░░░▒▓▓▓▓▓▒░░░░░▓▓ + ▓▒░░░░▒▓ ▓▓░░░░░▓▓ ▓▓░░░░▒▓▓▓▓▒░░░░░░░░░░░░░▒▓▓▓ ▓▓▓▓▒░░░░░░░░░░░░░▒▓▓▒░░░░░▓▓▓ ▓▓▒░░░░░▒▓ + ▓▓░░░▒▓▓ ▓▓▒░░░▒▓▓ ▓▓░░░░▓▓ ▓▓▓▓▒░░░░░░▒▒▓▓▓▓ ▓▓▓▓▓▒▒░░░░░▒▒▓▓▓▓▓░░░░▒▓▓ ▓▓▓░░░░▒▓ + ▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ + + '); + } + + public function welcome(): void + { + info('Welcome to Moox DataLanguages Installer'); + } + + public function publishConfiguration(): void + { + if (confirm('Do you wish to publish the configuration?', true)) { + if (! File::exists('config/data-languages.php')) { + info('Publishing DataLanguages Configuration...'); + $this->callSilent('vendor:publish', ['--tag' => 'data-languages-config']); + + return; + } + warning('The DataLanguages config already exist. The config will not be published.'); + } + } + + public function publishMigrations(): void + { + if (confirm('Do you wish to publish the migrations?', true)) { + if (Schema::hasTable('items')) { + warning('The items table already exists. The migrations will not be published.'); + + return; + } + info('Publishing DataLanguages Migrations...'); + $this->callSilent('vendor:publish', ['--tag' => 'data-languages-migrations']); + } + } + + public function runMigrations(): void + { + if (confirm('Do you wish to run the migrations?', true)) { + info('Running DataLanguages Migrations...'); + $this->callSilent('migrate'); + } + } + + public function registerPlugins(string $providerPath): void + { + if (File::exists($providerPath)) { + $content = File::get($providerPath); + + $intend = ' '; + + $namespace = "\Moox\DataLanguages"; + + $pluginsToAdd = multiselect( + label: 'These plugins will be installed:', + options: ['ItemPlugin'], + default: ['ItemPlugin'], + ); + + $function = '::make(),'; + + $pattern = '/->plugins\(\[([\s\S]*?)\]\);/'; + $newPlugins = ''; + + foreach ($pluginsToAdd as $plugin) { + $searchPlugin = '/'.$plugin.'/'; + if (preg_match($searchPlugin, $content)) { + warning("$plugin already registered."); + } else { + $newPlugins .= $intend.$namespace.'\\'.$plugin.$function."\n"; + } + } + + if ($newPlugins) { + if (preg_match($pattern, $content)) { + info('Plugins section found. Adding new plugins...'); + + $replacement = "->plugins([$1\n$newPlugins\n ]);"; + $newContent = preg_replace($pattern, $replacement, $content); + } else { + info('Plugins section created. Adding new plugins...'); + + $pluginsSection = " ->plugins([\n$newPlugins\n ]);"; + $placeholderPattern = '/(\->authMiddleware\(\[.*?\]\))\s*\;/s'; + $replacement = "$1\n".$pluginsSection; + $newContent = preg_replace($placeholderPattern, $replacement, $content, 1); + } + + File::put($providerPath, $newContent); + } + } else { + alert('There are no new plugins detected.'); + } + } + + public function registerPluginInPanelProvider(): void + { + $providerPath = app_path('Providers/Filament'); + $panelsToregister = $this->getPanelProviderPath(); + if ($panelsToregister != null) { + if (is_array($panelsToregister)) { + //Multiselect + foreach ($panelsToregister as $panelprovider) { + $this->registerPlugins($providerPath.'/'.$panelprovider); + } + } else { + //only one + $this->registerPlugins($panelsToregister); + } + } else { + alert('No PanelProvider Detected please register Plugins manualy.'); + } + } + + public function getPanelProviderPath(): string|array + { + $providerPath = app_path('Providers/Filament'); + $providers = File::allFiles($providerPath); + if (count($providers) > 1) { + $providerNames = []; + foreach ($providers as $provider) { + $providerNames[] = $provider->getBasename(); + } + $providerPath = multiselect( + label: 'Which Panel should it be registered', + options: [...$providerNames], + default: [$providerNames[0]], + ); + } + if (count($providers) == 1) { + $providerPath .= '/'.$providers[0]->getBasename(); + } + + return $providerPath; + } + + public function sayGoodbye(): void + { + note('Moox DataLanguages installed successfully. Enjoy!'); + } +} diff --git a/packages/data-languages/src/DataLanguagesServiceProvider.php b/packages/data-languages/src/DataLanguagesServiceProvider.php new file mode 100644 index 000000000..35d41a66f --- /dev/null +++ b/packages/data-languages/src/DataLanguagesServiceProvider.php @@ -0,0 +1,22 @@ +name('data-languages') + ->hasConfigFile() + ->hasViews() + ->hasTranslations() + ->hasMigrations() + ->hasCommands(); + } +} diff --git a/packages/data-languages/tests/ArchTest.php b/packages/data-languages/tests/ArchTest.php new file mode 100644 index 000000000..5b91a2933 --- /dev/null +++ b/packages/data-languages/tests/ArchTest.php @@ -0,0 +1,15 @@ +expect('Moox\DataLanguages') + ->toUseStrictTypes() + ->not->toUse(['die', 'dd', 'dump']); + +arch() + ->expect('Moox\DataLanguages\Models') + ->toBeClasses() + ->toExtend('Illuminate\Database\Eloquent\Model') + ->toOnlyBeUsedIn('Moox\DataLanguages'); + +arch()->preset()->php(); +arch()->preset()->security()->ignoring('md5'); diff --git a/packages/data-languages/tests/Feature/ExampleTest.php b/packages/data-languages/tests/Feature/ExampleTest.php new file mode 100644 index 000000000..61cd84c32 --- /dev/null +++ b/packages/data-languages/tests/Feature/ExampleTest.php @@ -0,0 +1,5 @@ +toBeTrue(); +}); diff --git a/packages/data-languages/tests/Pest.php b/packages/data-languages/tests/Pest.php new file mode 100644 index 000000000..e88faf717 --- /dev/null +++ b/packages/data-languages/tests/Pest.php @@ -0,0 +1,47 @@ +extends(TestCase::class) + ->beforeEach(function () { + $this->artisan('migrate'); + $user = User::factory()->create(); + $this->actingAs($user); + })->afterEach(function () { + $this->artisan('db:wipe'); + $this->artisan('optimize:clear'); + })->in('Feature'); + +/* +|-------------------------------------------------------------------------- +| Expectations +|-------------------------------------------------------------------------- +| +| When you're writing tests, you often need to check that values meet certain conditions. The +| "expect()" function gives you access to a set of "expectations" methods that you can use +| to assert different things. Of course, you may extend the Expectation API at any time. +| +*/ + +/* +|-------------------------------------------------------------------------- +| Functions +|-------------------------------------------------------------------------- +| +| While Pest is very powerful out-of-the-box, you may have some testing code specific to your +| project that you don't want to repeat in every file. Here you can also expose helpers as +| global functions to help you to reduce the number of lines of code in your test files. +| +*/ diff --git a/packages/data-languages/tests/TestCase.php b/packages/data-languages/tests/TestCase.php new file mode 100644 index 000000000..caa340663 --- /dev/null +++ b/packages/data-languages/tests/TestCase.php @@ -0,0 +1,59 @@ + 'VendorName\\DataLanguages\\Database\\Factories\\'.class_basename($modelName).'Factory' + ); + } + + protected function getPackageProviders($app) + { + return [ + DataLanguagesServiceProvider::class, + ]; + } + + public function getEnvironmentSetUp($app) + { + config()->set('database.default', 'testing'); + + /* + $migration = include __DIR__.'/../database/migrations/create_data-languages_table.php.stub'; + $migration->up(); + */ + } + + protected function setUpTestUser(): void + { + /* + $this->app['db']->connection()->getSchemaBuilder()->create('users', function (Blueprint $table) { + $table->id(); + $table->string('name'); + $table->string('email')->unique(); + $table->string('password'); + $table->timestamps(); + }); + + $user = new class extends User { + protected $table = 'users'; + }; + + $user::create([ + 'name' => 'Test User', + 'email' => 'test@example.com', + 'password' => bcrypt('password'), + ]); + */ + } +} diff --git a/packages/data-languages/tests/Unit/ExampleTest.php b/packages/data-languages/tests/Unit/ExampleTest.php new file mode 100644 index 000000000..61cd84c32 --- /dev/null +++ b/packages/data-languages/tests/Unit/ExampleTest.php @@ -0,0 +1,5 @@ +toBeTrue(); +});