diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..b0ee5d8 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,55 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +Please read and understand the contribution guide before creating an issue or pull request. + +## Etiquette + +This project is open source, and as such, the maintainers give their free time to build and maintain the source code +held within. They make the code freely available in the hope that it will be of use to other developers. It would be +extremely unfair for them to suffer abuse or anger for their hard work. + +Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the +world that developers are civilized and selfless people. + +It's the duty of the maintainer to ensure that all submissions to the project are of sufficient +quality to benefit the project. Many developers have different skills, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used. + +## Viability + +When requesting or submitting new features, first consider whether it might be useful to others. Open +source projects are used by many developers, who may have entirely different needs to your own. Think about +whether or not your feature is likely to be used by other users of the project. + +## Procedure + +Before filing an issue: + +- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident. +- Check to make sure your feature suggestion isn't already present within the project. +- Check the pull requests tab to ensure that the bug doesn't have a fix in progress. +- Check the pull requests tab to ensure that the feature isn't already in progress. + +Before submitting a pull request: + +- Check the codebase to ensure that your feature doesn't already exist. +- Check the pull requests to ensure that another person hasn't already submitted the feature or fix. + +## Requirements + +If the project maintainer has any additional requirements, you will find them listed here. + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +**Happy coding**! diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..892ba05 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [3x1io] diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..8fa85ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,66 @@ +name: Bug Report +description: Report an Issue or Bug with the Package +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + We're sorry to hear you have a problem. Can you help us solve it by providing the following details. + - type: textarea + id: what-happened + attributes: + label: What happened? + description: What did you expect to happen? + placeholder: I cannot currently do X thing because when I do, it breaks X thing. + validations: + required: true + - type: textarea + id: how-to-reproduce + attributes: + label: How to reproduce the bug + description: How did this occur, please add any config values used and provide a set of reliable steps if possible. + placeholder: When I do X I see Y. + validations: + required: true + - type: input + id: package-version + attributes: + label: Package Version + description: What version of our Package are you running? Please be as specific as possible + placeholder: 2.0.0 + validations: + required: true + - type: input + id: php-version + attributes: + label: PHP Version + description: What version of PHP are you running? Please be as specific as possible + placeholder: 8.2.0 + validations: + required: true + - type: input + id: laravel-version + attributes: + label: Laravel Version + description: What version of Laravel are you running? Please be as specific as possible + placeholder: 9.0.0 + validations: + required: true + - type: dropdown + id: operating-systems + attributes: + label: Which operating systems does with happen with? + description: You may select more than one. + multiple: true + options: + - macOS + - Windows + - Linux + - type: textarea + id: notes + attributes: + label: Notes + description: Use this field to provide any other notes that you feel might be relevant to the issue. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yaml b/.github/ISSUE_TEMPLATE/config.yaml new file mode 100644 index 0000000..977406a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yaml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Ask a question + url: https://github.com/tomatophp/filament-themes-manager/discussions/new?category=q-a + about: Ask the community for help + - name: Request a feature + url: https://github.com/tomatophp/filament-themes-manager/discussions/new?category=ideas + about: Share ideas for new features + - name: Report a security issue + url: https://github.com/tomatophp/filament-themes-manager/security/policy + about: Learn how to notify us for sensitive bugs diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..b2490a9 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,3 @@ +# Security Policy + +If you discover any security related issues, please email info@3x1.io instead of using the issue tracker. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0bc378d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 0000000..27c23a4 --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,32 @@ +name: dependabot-auto-merge +on: pull_request_target + +permissions: + pull-requests: write + contents: write + +jobs: + dependabot: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + steps: + + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v2.2.0 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Auto-merge Dependabot PRs for semver-minor updates + if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}} + run: gh pr merge --auto --merge "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + + - name: Auto-merge Dependabot PRs for semver-patch updates + if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}} + run: gh pr merge --auto --merge "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/fix-php-code-styling.yml b/.github/workflows/fix-php-code-styling.yml new file mode 100644 index 0000000..e71024d --- /dev/null +++ b/.github/workflows/fix-php-code-styling.yml @@ -0,0 +1,30 @@ +name: 'PHP Code Styling' + +on: + workflow_dispatch: + push: + branches: + - master + paths: + - '**.php' + +permissions: + contents: write + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - name: Fix PHP code style issues + uses: aglipanci/laravel-pint-action@v2 + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "Format Code" + commit_user_name: 'GitHub Actions' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..14a3ed3 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,68 @@ +name: "Tests" + +on: + workflow_dispatch: + push: + branches: + - master + paths: + - '**.php' + pull_request: + types: + - opened + - synchronize + branches: + - master + paths: + - '**.php' + - '.github/workflows/tests.yml' + - 'phpunit.xml.dist' + - 'composer.json' + - 'composer.lock' + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + os: [ubuntu-latest] + php: [8.3, 8.2] + laravel: [11.*] + stability: [prefer-stable] + include: + - laravel: 11.* + testbench: 9.* + carbon: 3.* + collision: 8.* + name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Cache Dependencies + uses: actions/cache@v4 + with: + path: ~/.composer/cache/files + key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo + coverage: none + + - name: Install Dependencies + run: | + echo "::add-matcher::${{ runner.tool_cache }}/php.json" + echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Install Dependencies + run: | + composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "nesbot/carbon:${{ matrix.carbon }}" "nunomaduro/collision:${{ matrix.collision }}" --no-interaction --no-update + composer update --${{ matrix.stability }} --prefer-dist --no-interaction + composer db + + - name: Execute tests + run: vendor/bin/pest diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..4123157 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,37 @@ +notPath('bootstrap/*') + ->notPath('storage/*') + ->notPath('resources/view/mail/*') + ->in([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + ->name('*.php') + ->notName('*.blade.php') + ->ignoreDotFiles(true) + ->ignoreVCS(true); + +return (new PhpCsFixer\Config()) + ->setRules([ + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'ordered_imports' => ['sort_algorithm' => 'alpha'], + 'no_unused_imports' => true, + 'not_operator_with_successor_space' => true, + 'trailing_comma_in_multiline' => true, + 'phpdoc_scalar' => true, + 'unary_operator_spaces' => true, + 'binary_operator_spaces' => true, + 'blank_line_before_statement' => [ + 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], + ], + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_var_without_name' => true, + 'method_argument_space' => [ + 'on_multiline' => 'ensure_fully_multiline', + 'keep_multiple_spaces_after_comma' => true, + ] + ]) + ->setFinder($finder); diff --git a/3x1io-tomato-themes-manager.md b/3x1io-tomato-themes-manager.md new file mode 100644 index 0000000..b10cafb --- /dev/null +++ b/3x1io-tomato-themes-manager.md @@ -0,0 +1,14 @@ +--- +name: Themes Manager +slug: 3x1io-tomato-themes-manager +author_slug: 3x1io +categories: [developer-tools] +description: Manage your frontend themes using Modules HMVC Arch and easy to use settings and upload support for FilamentPHP +discord_url: +docs_url: https://raw.githubusercontent.com/tomatophp/filament-themes-manager/master/README.md +github_repository: tomatophp/filament-themes-manager +has_dark_theme: true +has_translations: true +versions: [3] +publish_date: 2024-11-27 +--- diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e0a5086 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# V1.0.0 + +First release of the package diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..18c9147 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..e66364e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) + +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 new file mode 100644 index 0000000..bb1313c --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +![Screenshot](https://raw.githubusercontent.com/tomatophp/filament-themes-manager/master/art/screenshot.jpg) + +# Filament themes manager + +[![Latest Stable Version](https://poser.pugx.org/tomatophp/filament-themes-manager/version.svg)](https://packagist.org/packages/tomatophp/filament-themes-manager) +[![License](https://poser.pugx.org/tomatophp/filament-themes-manager/license.svg)](https://packagist.org/packages/tomatophp/filament-themes-manager) +[![Downloads](https://poser.pugx.org/tomatophp/filament-themes-manager/d/total.svg)](https://packagist.org/packages/tomatophp/filament-themes-manager) + +Manage your frontend themes using Modules HMVC Arch and easy to use settings and upload support for FilamentPHP + +## Installation + +```bash +composer require tomatophp/filament-themes-manager +``` +after install your package please run this command + +```bash +php artisan filament-themes-manager:install +``` + +finally register the plugin on `/app/Providers/Filament/AdminPanelProvider.php` + +```php +->plugin(\TomatoPHP\FilamentThemesManager\FilamentThemesManagerPlugin::make()) +``` + + +## Publish Assets + +you can publish config file by use this command + +```bash +php artisan vendor:publish --tag="filament-themes-manager-config" +``` + +you can publish views file by use this command + +```bash +php artisan vendor:publish --tag="filament-themes-manager-views" +``` + +you can publish languages file by use this command + +```bash +php artisan vendor:publish --tag="filament-themes-manager-lang" +``` + +you can publish migrations file by use this command + +```bash +php artisan vendor:publish --tag="filament-themes-manager-migrations" +``` + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. + +## Security + +Please see [SECURITY](SECURITY.md) for more information about security. + +## Credits + +- [Fady Mondy](mailto:info@3x1.io) + +## License + +The MIT License (MIT). Please see [License File](LICENSE.md) for more information. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..b2490a9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,3 @@ +# Security Policy + +If you discover any security related issues, please email info@3x1.io instead of using the issue tracker. diff --git a/arts/.gitkeep b/arts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..64cfcd8 --- /dev/null +++ b/composer.json @@ -0,0 +1,68 @@ +{ + "name": "tomatophp/filament-themes-manager", + "type": "library", + "description": "Manage your frontend themes using Modules HMVC Arch and easy to use settings and upload support for FilamentPHP", + "keywords": [ + "php", + "laravel", + "template" + ], + "license": "MIT", + "autoload": { + "psr-4": { + "TomatoPHP\\FilamentThemesManager\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "TomatoPHP\\FilamentThemesManager\\Tests\\": "tests/src/", + "TomatoPHP\\FilamentThemesManager\\Tests\\Database\\Factories\\": "tests/database/factories" + } + }, + "extra": { + "laravel": { + "providers": [ + "TomatoPHP\\FilamentThemesManager\\FilamentThemesManagerServiceProvider" + ] + } + }, + "authors": [ + { + "name": "Fady Mondy", + "email": "info@3x1.io" + } + ], + "config": { + "sort-packages": true, + "allow-plugins": { + "pestphp/pest-plugin": true, + "phpstan/extension-installer": true + } + }, + "scripts": { + "testbench": "vendor/bin/testbench package:discover --ansi", + "db": "vendor/bin/testbench package:create-sqlite-db && vendor/bin/testbench migrate", + "analyse": "vendor/bin/phpstan analyse src tests", + "test": "vendor/bin/pest", + "test-coverage": "vendor/bin/pest --coverage", + "format": "vendor/bin/pint" + }, + "require": { + "php": "^8.1|^8.2", + "tomatophp/console-helpers": "^1.1", + "filament/filament": "^3.2" + }, + "require-dev": { + "laravel/pint": "^1.18", + "livewire/livewire": "^2.10|^3.0", + "nunomaduro/larastan": "^2.9", + "orchestra/testbench": "^9.5", + "pestphp/pest": "^2.36", + "pestphp/pest-plugin-laravel": "^2.4", + "pestphp/pest-plugin-livewire": "^2.1", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan-deprecation-rules": "^1.2", + "phpstan/phpstan-phpunit": "^1.4" + }, + "version": "v1.0.0" +} diff --git a/config/.gitkeep b/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/config/filament-themes-manager.php b/config/filament-themes-manager.php new file mode 100644 index 0000000..c5c1d6e --- /dev/null +++ b/config/filament-themes-manager.php @@ -0,0 +1,10 @@ + [ + "scan" => true, + "sections" => [ + "/vendor/tomatophp/filament-cms/src/Sections" + ] + ] +]; diff --git a/database/migrations/2023_11_23_190637_themes_settings.php b/database/migrations/2023_11_23_190637_themes_settings.php new file mode 100644 index 0000000..9414abf --- /dev/null +++ b/database/migrations/2023_11_23_190637_themes_settings.php @@ -0,0 +1,40 @@ +migrator->add('themes.theme_name', 'main'); + $this->migrator->add('themes.theme_path', 'themes.main'); + $this->migrator->add('themes.theme_namespace', ''); + $this->migrator->add('themes.theme_main_color', ''); + $this->migrator->add('themes.theme_secandry_color', ''); + $this->migrator->add('themes.theme_sub_color', ''); + $this->migrator->add('themes.theme_css', ''); + $this->migrator->add('themes.theme_js', ''); + $this->migrator->add('themes.theme_header', ''); + $this->migrator->add('themes.theme_footer', ''); + $this->migrator->add('themes.theme_copyright', ''); + } + } + + public function down(): void + { + if(config('filament-cms.features.theme-manager')) { + $this->migrator->delete('themes.theme_name'); + $this->migrator->delete('themes.theme_path'); + $this->migrator->delete('themes.theme_namespace'); + $this->migrator->delete('themes.theme_main_color'); + $this->migrator->delete('themes.theme_secandry_color'); + $this->migrator->delete('themes.theme_sub_color'); + $this->migrator->delete('themes.theme_css'); + $this->migrator->delete('themes.theme_js'); + $this->migrator->delete('themes.theme_header'); + $this->migrator->delete('themes.theme_footer'); + $this->migrator->delete('themes.theme_copyright'); + } + } +}; diff --git a/module.json b/module.json new file mode 100644 index 0000000..9d98a15 --- /dev/null +++ b/module.json @@ -0,0 +1,29 @@ +{ + "name": "FilamentThemesManager", + "alias": "filament-themes-manager", + "description": { + "ar": "Manage your frontend themes using Modules HMVC Arch and easy to use settings and upload support for FilamentPHP", + "en": "Manage your frontend themes using Modules HMVC Arch and easy to use settings and upload support for FilamentPHP", + "gr": "Manage your frontend themes using Modules HMVC Arch and easy to use settings and upload support for FilamentPHP", + "sp": "Manage your frontend themes using Modules HMVC Arch and easy to use settings and upload support for FilamentPHP" + }, + "keywords": [], + "priority": 0, + "providers": [ + "TomatoPHP\\FilamentThemesManager\\FilamentThemesManagerServiceProvider" + ], + "files": [], + "title": { + "ar": "Filament themes manager", + "en": "Filament themes manager", + "gr": "Filament themes manager", + "sp": "Filament themes manager" + }, + "color": "#cc1448", + "icon": "heroicon-c-users", + "placeholder": "https://raw.githubusercontent.com/tomatophp/filament-themes-manager/master/art/screenshot.jpg", + "type": "plugin", + "version": "v1.0.0", + "github" : "https://github.com/tomatophp/filament-themes-manager", + "docs" : "https://github.com/tomatophp/filament-themes-manager" +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..e542661 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,26 @@ + + + + + ./tests/ + + + + + ./src + + + + + + + diff --git a/pint.json b/pint.json new file mode 100644 index 0000000..c6ddb49 --- /dev/null +++ b/pint.json @@ -0,0 +1,14 @@ +{ + "preset": "laravel", + "rules": { + "blank_line_before_statement": true, + "concat_space": { + "spacing": "one" + }, + "method_argument_space": true, + "single_trait_insert_per_statement": true, + "types_spaces": { + "space": "single" + } + } +} diff --git a/resources/lang/.gitkeep b/resources/lang/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resources/lang/ar/messages.php b/resources/lang/ar/messages.php new file mode 100644 index 0000000..4436203 --- /dev/null +++ b/resources/lang/ar/messages.php @@ -0,0 +1,30 @@ + [ + "title" => "القوالب", + "single" => "القالب", + "actions" => [ + "active" => "تفعيل", + "disable" => "تعطيل", + ], + "notifications" => [ + "autoload" => [ + "title" => "فشل تحميل القالب", + "body" => "فشل تحميل القالب", + ], + "enabled" => [ + "title" => "تم تفعيل القالب", + "body" => "تم تفعيل القالب بنجاح", + ], + "disabled" => [ + "title" => "تم تعطيل القالب", + "body" => "تم تعطيل القالب بنجاح", + ], + "deleted" => [ + "title" => "تم حذف القالب", + "body" => "تم حذف القالب بنجاح", + ], + ], + ], +]; diff --git a/resources/lang/en/messages.php b/resources/lang/en/messages.php new file mode 100644 index 0000000..96e6149 --- /dev/null +++ b/resources/lang/en/messages.php @@ -0,0 +1,30 @@ + [ + "title" => "Themes", + "single" => "Theme", + "actions" => [ + "active" => "Active", + "disable" => "Disable", + ], + "notifications" => [ + "autoload" => [ + "title" => "Autoload Error", + "body" => "The theme autoload class does not exist", + ], + "enabled" => [ + "title" => "Theme Enabled", + "body" => "The theme has been enabled successfully", + ], + "disabled" => [ + "title" => "Theme Disabled", + "body" => "The theme has been disabled successfully", + ], + "deleted" => [ + "title" => "Theme Deleted", + "body" => "The theme has been deleted successfully", + ], + ], + ], +]; diff --git a/resources/views/.gitkeep b/resources/views/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resources/views/pages/table.blade.php b/resources/views/pages/table.blade.php new file mode 100644 index 0000000..5989759 --- /dev/null +++ b/resources/views/pages/table.blade.php @@ -0,0 +1,64 @@ +
+ @foreach($records as $item) +
+ + @if($item['placeholder'] !== 'placeholder.webp') +
+ +
+ @else +
+
+ +
+
+ @endif +
+
+

{{ json_decode($item['name'])->{app()->getLocale()} }}

+
+
+

{{ $item['version'] }}

+
+
+
+

+ {{ json_decode($item['description'])->{app()->getLocale()} }} +

+
+
+
+ @if($item['type'] !== 'lib') + @if((bool)config('filament-plugins.allow_toggle')) + @if($item->active) + {{ ($this->disableAction)(['item' => $item]) }} + @else + {{ ($this->activeAction)(['item' => $item]) }} + @endif + + @endif + @if((bool)config('filament-plugins.allow_destroy')) + {{ ($this->deleteAction)(['item' => $item])}} + @endif + @endif +
+
+ @if($item->github) + + + + + + @endif + @if($item->docs) + + + + + + @endif +
+
+
+ @endforeach +
diff --git a/resources/views/pages/themes.blade.php b/resources/views/pages/themes.blade.php new file mode 100644 index 0000000..ce096a2 --- /dev/null +++ b/resources/views/pages/themes.blade.php @@ -0,0 +1,3 @@ + + {{ $this->table }} + diff --git a/src/Console/.gitkeep b/src/Console/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/Console/FilamentThemeGenerator.php b/src/Console/FilamentThemeGenerator.php new file mode 100644 index 0000000..2411845 --- /dev/null +++ b/src/Console/FilamentThemeGenerator.php @@ -0,0 +1,71 @@ +generate(); + + }, + 'Generate Theme ...' + ); + + \Laravel\Prompts\info('Theme generated successfully'); + + shell_exec('composer dump-autoload'); + + } +} diff --git a/src/Console/FilamentThemesManagerInstall.php b/src/Console/FilamentThemesManagerInstall.php new file mode 100644 index 0000000..8d5897e --- /dev/null +++ b/src/Console/FilamentThemesManagerInstall.php @@ -0,0 +1,44 @@ +info('Publish Vendor Assets'); + $this->artisanCommand(["migrate"]); + $this->artisanCommand(["optimize:clear"]); + $this->info('Filament themes manager installed successfully.'); + } +} diff --git a/src/Filament/Pages/Themes.php b/src/Filament/Pages/Themes.php new file mode 100644 index 0000000..e61eaec --- /dev/null +++ b/src/Filament/Pages/Themes.php @@ -0,0 +1,150 @@ +iconButton() + ->icon('heroicon-s-x-circle') + ->color('danger') + ->tooltip(trans('filament-cms::messages.themes.actions.disable')) + ->requiresConfirmation() + ->action(function (array $arguments) { + $module = Module::find($arguments['item']['module_name']); + $module?->disable(); + + $setting = new ThemesSettings(); + $setting->theme_name = null; + $setting->save(); + + Notification::make() + ->title(trans('filament-cms::messages.themes.notifications.disabled.title')) + ->body(trans('filament-cms::messages.themes.notifications.disabled.body')) + ->success() + ->send(); + + $this->js('window.location.reload()'); + }); + } + + public function deleteAction(): Action + { + return Action::make('delete') + ->iconButton() + ->icon('heroicon-s-trash') + ->color('danger') + ->tooltip(trans('filament-cms::messages.themes.actions.delete')) + ->requiresConfirmation() + ->action(function (array $arguments) { + $module = Module::find($arguments['item']['module_name']); + $module?->delete(); + + Notification::make() + ->title(trans('filament-cms::messages.themes.notifications.deleted.title')) + ->body(trans('filament-cms::messages.themes.notifications.deleted.body')) + ->success() + ->send(); + + $this->js('window.location.reload()'); + }); + } + + + public function activeAction(): Action + { + return Action::make('active') + ->iconButton() + ->icon('heroicon-s-check-circle') + ->tooltip(trans('filament-cms::messages.themes.actions.active')) + ->color('success') + ->requiresConfirmation() + ->action(function (array $arguments) { + if(!class_exists(json_decode($arguments['item']['providers'])[0])){ + Notification::make() + ->title(trans('filament-cms::messages.themes.notifications.autoload.title')) + ->body(trans('filament-cms::messages.themes.notifications.autoload.body')) + ->danger() + ->send(); + return; + } + $module = Module::find($arguments['item']['module_name']); + $module?->enable(); + + $themes = Theme::all(); + foreach ($themes as $theme){ + if($theme->module_name != $arguments['item']['module_name']) { + $module = Module::find($theme->module_name); + $module?->disable(); + } + } + + $setting = new ThemesSettings(); + $setting->theme_name = $arguments['item']['module_name']; + $setting->save(); + + Notification::make() + ->title(trans('filament-cms::messages.themes.notifications.enabled.title')) + ->body(trans('filament-cms::messages.themes.notifications.enabled.body')) + ->success() + ->send(); + + $this->js('window.location.reload()'); + + }); + } + + + + public function table(Table $table): Table + { + return $table + ->query(Theme::query()) + ->content(function () { + return view('filament-cms::pages.table'); + }) + ->columns([ + TextColumn::make('name') + ->label(trans('filament-cms::messages.themes.form.name')) + ->searchable(), + ]); + } +} diff --git a/src/Filament/Pages/Traits/HasShield.php b/src/Filament/Pages/Traits/HasShield.php new file mode 100644 index 0000000..e53a834 --- /dev/null +++ b/src/Filament/Pages/Traits/HasShield.php @@ -0,0 +1,75 @@ +isShieldAllowed()){ + $this->beforeBooted(); + + if (! static::canAccess()) { + + Notification::make() + ->title(__('filament-shield::filament-shield.forbidden')) + ->warning() + ->send(); + + $this->beforeShieldRedirects(); + + redirect($this->getShieldRedirectPath()); + + return; + } + + if (method_exists(parent::class, 'booted')) { + parent::booted(); + } + + $this->afterBooted(); + } + } + + protected function beforeBooted(): void + { + } + + protected function afterBooted(): void + { + } + + protected function beforeShieldRedirects(): void + { + } + + protected function getShieldRedirectPath(): string + { + return Filament::getUrl(); + } + + protected static function getPermissionName(): string + { + return Str::of(class_basename(static::class)) + ->prepend( + Str::of(Utils::getPagePermissionPrefix()) + ->append('_') + ->toString() + ) + ->toString(); + } + + public static function canAccess(): bool + { + if(filament('filament-cms')->isShieldAllowed()){ + return Filament::auth()->user()->can(static::getPermissionName()); + } + else { + return true; + } + } +} diff --git a/src/FilamentThemesManagerPlugin.php b/src/FilamentThemesManagerPlugin.php new file mode 100644 index 0000000..b9e2947 --- /dev/null +++ b/src/FilamentThemesManagerPlugin.php @@ -0,0 +1,30 @@ +commands([ + \TomatoPHP\FilamentThemesManager\Console\FilamentThemesManagerInstall::class, + ]); + + //Register Config file + $this->mergeConfigFrom(__DIR__.'/../config/filament-themes-manager.php', 'filament-themes-manager'); + + //Publish Config + $this->publishes([ + __DIR__.'/../config/filament-themes-manager.php' => config_path('filament-themes-manager.php'), + ], 'filament-themes-manager-config'); + + //Register Migrations + $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); + + //Publish Migrations + $this->publishes([ + __DIR__.'/../database/migrations' => database_path('migrations'), + ], 'filament-themes-manager-migrations'); + //Register views + $this->loadViewsFrom(__DIR__.'/../resources/views', 'filament-themes-manager'); + + //Publish Views + $this->publishes([ + __DIR__.'/../resources/views' => resource_path('views/vendor/filament-themes-manager'), + ], 'filament-themes-manager-views'); + + //Register Langs + $this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'filament-themes-manager'); + + //Publish Lang + $this->publishes([ + __DIR__.'/../resources/lang' => base_path('lang/vendor/filament-themes-manager'), + ], 'filament-themes-manager-lang'); + + //Register Routes + $this->loadRoutesFrom(__DIR__.'/../routes/web.php'); + + } + + public function boot(): void + { + //you boot methods here + } +} diff --git a/src/Generator/GenerateTheme.php b/src/Generator/GenerateTheme.php new file mode 100644 index 0000000..c1dff64 --- /dev/null +++ b/src/Generator/GenerateTheme.php @@ -0,0 +1,43 @@ +themeTitle = $themeName; + $this->themeName = Str::of($themeName)->camel()->ucfirst()->toString(); + $this->stubPath = __DIR__ . '/../../stubs/'; + $this->publish = __DIR__ . '/../../stubs/'; + } + + /** + * @return void + */ + public function generate(): void + { + $this->generateModule(); + $this->generateReadMe(); + $this->generateInfo(); + } +} diff --git a/src/Generator/Traits/GenerateInfo.php b/src/Generator/Traits/GenerateInfo.php new file mode 100644 index 0000000..9b0506f --- /dev/null +++ b/src/Generator/Traits/GenerateInfo.php @@ -0,0 +1,39 @@ +themeName)){ + $modulePath = module_path($this->themeName) .'/module.json'; + $module = json_decode(File::get($modulePath)); + $module->title = []; + $module->title['ar'] = $this->themeTitle; + $module->title['en'] = $this->themeTitle; + $module->title['gr'] = $this->themeTitle; + $module->title['sp'] = $this->themeTitle; + $module->description = []; + $module->description['ar'] = $this->themeDescription; + $module->description['en'] = $this->themeDescription; + $module->description['gr'] = $this->themeDescription; + $module->description['sp'] = $this->themeDescription; + $module->placeholder = "placeholder.webp"; + $module->type = "theme"; + $module->color = "#F01E19"; + $module->icon = "heroicon-s-swatch"; + $module->version = "v1.0.0"; + + File::put($modulePath, json_encode($module, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); + } + + } +} diff --git a/src/Generator/Traits/GenerateModule.php b/src/Generator/Traits/GenerateModule.php new file mode 100644 index 0000000..cdfe4b6 --- /dev/null +++ b/src/Generator/Traits/GenerateModule.php @@ -0,0 +1,14 @@ +themeName); + sleep(3); + } +} diff --git a/src/Generator/Traits/GenerateReadMe.php b/src/Generator/Traits/GenerateReadMe.php new file mode 100644 index 0000000..0a26fec --- /dev/null +++ b/src/Generator/Traits/GenerateReadMe.php @@ -0,0 +1,28 @@ +generateStubs( + $this->stubPath . 'readme.stub', + base_path("Modules") . '/'. $this->themeName . '/README.md', + [ + "name" => $this->themeName, + "description" => $this->themeDescription, + ], + [ + base_path("Modules"), + base_path("Modules") . "/". $this->themeName, + ] + ); + } +} diff --git a/src/Models/.gitkeep b/src/Models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/Models/Theme.php b/src/Models/Theme.php new file mode 100644 index 0000000..3dd157e --- /dev/null +++ b/src/Models/Theme.php @@ -0,0 +1,103 @@ + 'string', + 'title' => 'json', + 'description' => 'json', + 'color' => 'string', + 'placeholder' => 'string', + 'icon' => 'string', + 'version' => 'string', + 'docs' => 'string', + 'github' => 'string', + 'active' => 'boolean', + 'providers' => 'json', + 'type' => 'string', + ]; + + public function getRows() + { + $getPlugins = []; + if(File::exists(base_path('Modules'))){ + $getPlugins = collect(File::directories(base_path('Modules'))); + $getPlugins = $getPlugins->filter(function ($item) { + $json = json_decode(File::get($item . "/module.json")); + if (isset($json->type) && $json->type === 'theme'){ + return true; + } + else { + return false; + } + })->transform(callback: static function($item){ + $info = json_decode(File::get($item . "/module.json")); + return [ + "module_name" => $info->name, + "name" => json_encode($info->title), + "description" => json_encode($info->description), + "color" => $info->color, + "placeholder" => $info->placeholder, + "version" => $info->version, + "type" => $info->type, + "icon" => $info->icon, + "github" => isset($info->github)?$info->github:null, + "docs" => isset($info->docs)?$info->docs:null, + "active" => Module::find($info->name)->isEnabled(), + "providers" => json_encode($info->providers) + ]; + }); + } + + $providersPlugins = []; + if(config('filament-cms.themes.scan')){ + $getVendorPathes = File::directories(base_path('vendor')); + foreach ($getVendorPathes as $item){ + $checkInsideDir = File::directories($item); + foreach ($checkInsideDir as $dir){ + $getDirFiles = File::files($dir); + foreach ($getDirFiles as $file){ + if (str($file->getFilename())->contains('filament-theme.json')){ + $info = json_decode($file->getContents()); + $providersPlugins[] = [ + "module_name" => $info->name, + "name" => json_encode($info->title), + "description" => json_encode($info->description), + "color" => $info->color, + "type" => $info->type, + "placeholder" => $info->placeholder, + "version" => $info->version, + "icon" => $info->icon, + "github" => isset($info->github)?$info->github:null, + "docs" => isset($info->docs)?$info->docs:null, + "active" => false, + "providers" => json_encode($info->providers) + ]; + } + } + } + } + } + + if(is_array($getPlugins)){ + $values = array_values($getPlugins); + } + else { + $values = array_values($getPlugins->toArray()); + } + + + return array_merge($values, array_values($providersPlugins)); + } +} diff --git a/src/Services/Contracts/Section.php b/src/Services/Contracts/Section.php new file mode 100644 index 0000000..0fafbf6 --- /dev/null +++ b/src/Services/Contracts/Section.php @@ -0,0 +1,95 @@ +key($key); + } + + public function toArray(): array + { + return [ + 'hasForm' => $this->hasForm, + 'type' => $this->type, + 'label' => $this->label, + 'key' => $this->key, + 'view' => $this->view, + 'color' => $this->color, + 'icon' => $this->icon, + 'form' => $this->form, + 'lock' => $this->lock, + ]; + } + + public function label(string $label): static + { + $this->label = $label; + return $this; + } + + + public function type(string $type): static + { + $this->type = $type; + return $this; + } + + public function form(array $form): static + { + $this->form = $form; + $this->hasForm = true; + return $this; + } + + public function key(string $key): static + { + $this->key = $key; + return $this; + } + + public function view(string $view): static + { + if(view()->exists($view)){ + $this->view = $view; + } + else { + throw new \Exception("View not found"); + } + + return $this; + } + + public function color(string $color): static + { + $this->color = $color; + return $this; + } + + public function icon(string $icon): static + { + $this->icon = $icon; + return $this; + } + + public function lock(string $lock): static + { + $this->lock = $lock; + return $this; + } +} diff --git a/src/Services/FilamentCMSThemes.php b/src/Services/FilamentCMSThemes.php new file mode 100644 index 0000000..b968c55 --- /dev/null +++ b/src/Services/FilamentCMSThemes.php @@ -0,0 +1,31 @@ +settings->{$key})){ + return $info->settings->{$key}->value; + } + + $settingClass = new \TomatoPHP\FilamentThemesManager\Settings\ThemesSettings(); + + if(isset($settingClass->{'theme_'.$key})){ + return $settingClass->{'theme_'.$key}; + } + + return false; + } +} + +if(!function_exists('load_page')){ + function load_page(string $slug,string $name=null): Post + { + $page = Post::query() + ->withTrashed() + ->where('type', 'builder') + ->where('slug', $slug) + ->first(); + + if(!$page){ + $page = new Post(); + $page->title = $name ?: 'Empty'; + $page->type = 'builder'; + $page->slug = $slug; + $page->is_published = true; + $page->save(); + } + else { + if($page->deleted_at){ + $page->restore(); + } + } + + return $page; + } +} + +if(!function_exists('section')){ + function section($key): ?\TomatoPHP\FilamentThemesManager\Services\Contracts\Section + { + $section = \TomatoPHP\FilamentThemesManager\Facades\FilamentCMS::themes()->getSections()->where('key', $key)->first(); + return $section??null; + } +} + diff --git a/stubs/migration.stub b/stubs/migration.stub new file mode 100644 index 0000000..e0e7349 --- /dev/null +++ b/stubs/migration.stub @@ -0,0 +1,129 @@ +fields = [ + {{ fields }} + ]; + } + + /** + * Run the migrations. + * + * @return void + */ + public function up(): void + { + $fields = $this->fields; + DB::transaction(function () use ($fields){ + $fieldsIds = []; + foreach($fields as $field) { + $fieldExists = DB::table('fields')->where([ + 'key' => $field['key'], + ])->first(); + if ($fieldExists === null) { + DB::table('fields')->insert([ + "label" => $field['label'], + "key" => $field['key'], + "type"=> $field['type'], + "placeholder" => $field['placeholder'], + "is_required" => $field['is_required'], + "has_options" => $field['has_options'], + ]); + + $fieldsIds[] = DB::getPdo()->lastInsertId(); + + if($field['is_required']){ + $options = explode(',', $field['options']); + $options = array_map(function ($option){ + return trim($option); + }, $options); + foreach($options as $option){ + DB::table('field_options')->insert([ + "field_id" => DB::getPdo()->lastInsertId(), + 'type' => 'text', + 'label' => $option, + 'value' => $option, + ]); + } + } + } + else { + $fieldsIds[] = $fieldExists->id; + } + } + + + $fromExists = DB::table('forms')->where([ + 'key' => '{{ key }}', + ])->first(); + if ($fromExists === null) { + DB::table('forms') + ->insert([ + "title" => "{{ formTitle }}", + "key" => "{{ key }}", + "endpoint" => "{{ formEndpoint }}", + "method" => "{{ formMethod }}", + "description" => "{{ formDescription }}", + "type" => "{{ formType }}" + ]); + } + + $formId = DB::table('forms')->where([ + 'key' => '{{ key }}', + ])->first()->id; + + foreach($fieldsIds as $fieldKey=>$fieldItem){ + $checkExists = DB::table('form_has_fields')->where([ + "form_id" => $formId, + "field_id" => $fieldItem, + ])->first(); + if($checkExists === null){ + DB::table('form_has_fields')->insert([ + "form_id" => $formId, + "field_id" => $fieldItem, + "order" => $fieldKey, + ]); + } + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down(): void + { + $fields = $this->fields; + DB::transaction(function () use ($fields){ + foreach($fields as $field) { + $filedID = DB::table('fields')->where([ + 'key' => $field['key'], + ])->first()->id; + + DB::table('field_options')->where([ + 'field_id' => $filedID, + ])->delete(); + + DB::table('fields')->where([ + 'key' => $field['key'], + ])->delete(); + } + DB::table('forms')->where([ + 'key' => '{{ key }}', + ])->delete(); + }); + } +} diff --git a/stubs/readme.stub b/stubs/readme.stub new file mode 100644 index 0000000..a0be2b0 --- /dev/null +++ b/stubs/readme.stub @@ -0,0 +1,27 @@ +# {{ name }} + +{{ description }} + +## Installation + +download repo as zip and upload it to your tomato project + +## Support + +you can join our discord server to get support [TomatoPHP](https://discord.gg/Xqmt35Uh) + +## Docs + +you can check docs of this package on [Docs](https://docs.tomatophp.com/plugins/tomato-themes) + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. + +## Security + +Please see [SECURITY](SECURITY.md) for more information about security. + +## License + +The MIT License (MIT). Please see [License File](LICENSE.md) for more information. diff --git a/testbench.yaml b/testbench.yaml new file mode 100644 index 0000000..dcbfdcb --- /dev/null +++ b/testbench.yaml @@ -0,0 +1,24 @@ +providers: + - BladeUI\Icons\BladeIconsServiceProvider + - BladeUI\Heroicons\BladeHeroiconsServiceProvider + - Filament\Actions\ActionsServiceProvider + - Filament\FilamentServiceProvider + - Filament\Forms\FormsServiceProvider + - Filament\Infolists\InfolistsServiceProvider + - Filament\Notifications\NotificationsServiceProvider + - Filament\Support\SupportServiceProvider + - Filament\Tables\TablesServiceProvider + - Filament\Widgets\WidgetsServiceProvider + - RyanChandler\BladeCaptureDirective\BladeCaptureDirectiveServiceProvider + - TomatoPHP\FilamentThemesManager\FilamentThemesManagerServiceProvider + - TomatoPHP\FilamentThemesManager\Tests\AdminPanelProvider +workbench: + welcome: true + install: true + start: / + guard: testing + discovers: + web: true + api: false + commands: false + views: true diff --git a/tests/Pest.php b/tests/Pest.php new file mode 100644 index 0000000..63a9fb6 --- /dev/null +++ b/tests/Pest.php @@ -0,0 +1,5 @@ +in(__DIR__); diff --git a/tests/database/database.sqlite b/tests/database/database.sqlite new file mode 100644 index 0000000..cb9c456 Binary files /dev/null and b/tests/database/database.sqlite differ diff --git a/tests/database/factories/.gitkeep b/tests/database/factories/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/database/factories/UserFactory.php b/tests/database/factories/UserFactory.php new file mode 100644 index 0000000..c08bc4c --- /dev/null +++ b/tests/database/factories/UserFactory.php @@ -0,0 +1,23 @@ + $this->faker->name(), + 'email' => $this->faker->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password + 'remember_token' => Str::random(10), + ]; + } +} diff --git a/tests/src/AdminPanelProvider.php b/tests/src/AdminPanelProvider.php new file mode 100644 index 0000000..fbd8eb2 --- /dev/null +++ b/tests/src/AdminPanelProvider.php @@ -0,0 +1,50 @@ +default() + ->id('admin') + ->path('admin') + ->login() + ->pages([ + Pages\Dashboard::class, + ]) + ->plugin( + FilamentThemesManagerPlugin::make() + ) + ->middleware([ + EncryptCookies::class, + AddQueuedCookiesToResponse::class, + StartSession::class, + AuthenticateSession::class, + ShareErrorsFromSession::class, + VerifyCsrfToken::class, + SubstituteBindings::class, + DisableBladeIconComponents::class, + DispatchServingFilamentEvent::class, + ]) + ->authMiddleware([ + Authenticate::class, + ]); + } +} diff --git a/tests/src/DebugTest.php b/tests/src/DebugTest.php new file mode 100644 index 0000000..91bf6cd --- /dev/null +++ b/tests/src/DebugTest.php @@ -0,0 +1,5 @@ +each->not->toBeUsed(); +}); diff --git a/tests/src/Models/.gitkeep b/tests/src/Models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/src/Models/User.php b/tests/src/Models/User.php new file mode 100644 index 0000000..d97b774 --- /dev/null +++ b/tests/src/Models/User.php @@ -0,0 +1,34 @@ +set('database.default', 'sqlite'); + $app['config']->set('database.connections.sqlite.database', __DIR__ . '/../database/database.sqlite'); + + $app['config']->set('view.paths', [ + ...$app['config']->get('view.paths'), + __DIR__ . '/../resources/views', + ]); + } +}