├── .github └── workflows │ └── main.yaml.dist ├── .gitignore ├── .php-cs-fixer.dist.php ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src ├── FooBundle.php └── Resources │ └── config │ └── services.php └── tests └── App ├── AppKernel.php ├── Func └── FooServiceTest.php ├── Unit └── FooFactoryTest.php └── packages └── config.yaml /.github/workflows/main.yaml.dist: -------------------------------------------------------------------------------- 1 | name: Main 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | php-cs-fixer: 9 | runs-on: ubuntu-latest 10 | name: Coding Standards 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | 15 | - name: Setup PHP 16 | uses: shivammathur/setup-php@v2 17 | with: 18 | php-version: '8.1' 19 | tools: php-cs-fixer 20 | 21 | - name: PHP Coding Standards Fixer 22 | run: php-cs-fixer --diff --dry-run --using-cache=no -v fix src 23 | 24 | php-stan: 25 | runs-on: ubuntu-latest 26 | name: PHPStan 27 | steps: 28 | - uses: actions/checkout@v2 29 | - uses: php-actions/composer@v6 # or alternative dependency management 30 | - uses: php-actions/phpstan@v3 31 | with: 32 | path: src/ 33 | level: 9 34 | 35 | phpunit: 36 | runs-on: ubuntu-latest 37 | strategy: 38 | matrix: 39 | php-versions: ['8.1'] 40 | fail-fast: false 41 | name: PHP ${{ matrix.php-versions }} tests 42 | steps: 43 | - name: Checkout 44 | uses: actions/checkout@v2 45 | 46 | - name: Setup PHP 47 | uses: shivammathur/setup-php@v2 48 | with: 49 | php-version: ${{ matrix.php-versions }} 50 | 51 | - name: Get composer cache directory 52 | id: composercache 53 | run: echo "::set-output name=dir::$(composer config cache-files-dir)" 54 | 55 | - name: Cache dependencies 56 | uses: actions/cache@v2 57 | with: 58 | path: ${{ steps.composercache.outputs.dir }} 59 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} 60 | restore-keys: ${{ runner.os }}-composer- 61 | 62 | - name: Install dependencies 63 | run: composer install --prefer-dist 64 | 65 | - name: Run tests 66 | run: vendor/bin/phpunit 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | 3 | .php-cs-fixer.cache 4 | .phpunit.result.cache 5 | 6 | var/ 7 | vendor/ 8 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in(__DIR__.'/{src,tests}') 5 | ; 6 | 7 | $config = new PhpCsFixer\Config(); 8 | 9 | return $config 10 | ->setRules([ 11 | '@Symfony' => true, 12 | 'concat_space' => ['spacing' => 'none'], 13 | 'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'], 14 | 'array_syntax' => ['syntax' => 'short'], 15 | 'ordered_imports' => ['sort_algorithm' => 'alpha'], 16 | ]) 17 | ->setRiskyAllowed(true) 18 | ->setLineEnding("\n") 19 | ->setFinder($finder) 20 | ->setCacheFile(__DIR__.'/.php-cs-fixer.cache') 21 | ; 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 17 | ## Code of Conduct 18 | 19 | ### Our Pledge 20 | 21 | In the interest of fostering an open and welcoming environment, we as 22 | contributors and maintainers pledge to making participation in our project and 23 | our community a harassment-free experience for everyone, regardless of age, body 24 | size, disability, ethnicity, gender identity and expression, level of experience, 25 | nationality, personal appearance, race, religion, or sexual identity and 26 | orientation. 27 | 28 | ### Our Standards 29 | 30 | Examples of behavior that contributes to creating a positive environment 31 | include: 32 | 33 | * Using welcoming and inclusive language 34 | * Being respectful of differing viewpoints and experiences 35 | * Gracefully accepting constructive criticism 36 | * Focusing on what is best for the community 37 | * Showing empathy towards other community members 38 | 39 | Examples of unacceptable behavior by participants include: 40 | 41 | * The use of sexualized language or imagery and unwelcome sexual attention or 42 | advances 43 | * Trolling, insulting/derogatory comments, and personal or political attacks 44 | * Public or private harassment 45 | * Publishing others' private information, such as a physical or electronic 46 | address, without explicit permission 47 | * Other conduct which could reasonably be considered inappropriate in a 48 | professional setting 49 | 50 | ### Our Responsibilities 51 | 52 | Project maintainers are responsible for clarifying the standards of acceptable 53 | behavior and are expected to take appropriate and fair corrective action in 54 | response to any instances of unacceptable behavior. 55 | 56 | Project maintainers have the right and responsibility to remove, edit, or 57 | reject comments, commits, code, wiki edits, issues, and other contributions 58 | that are not aligned to this Code of Conduct, or to ban temporarily or 59 | permanently any contributor for other behaviors that they deem inappropriate, 60 | threatening, offensive, or harmful. 61 | 62 | ### Scope 63 | 64 | This Code of Conduct applies both within project spaces and in public spaces 65 | when an individual is representing the project or its community. Examples of 66 | representing a project or community include using an official project e-mail 67 | address, posting via an official social media account, or acting as an appointed 68 | representative at an online or offline event. Representation of a project may be 69 | further defined and clarified by project maintainers. 70 | 71 | ### Enforcement 72 | 73 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 74 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 75 | complaints will be reviewed and investigated and will result in a response that 76 | is deemed necessary and appropriate to the circumstances. The project team is 77 | obligated to maintain confidentiality with regard to the reporter of an incident. 78 | Further details of specific enforcement policies may be posted separately. 79 | 80 | Project maintainers who do not follow or enforce the Code of Conduct in good 81 | faith may face temporary or permanent repercussions as determined by other 82 | members of the project's leadership. 83 | 84 | ### Attribution 85 | 86 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 87 | available at [http://contributor-covenant.org/version/1/4][version] 88 | 89 | [homepage]: http://contributor-covenant.org 90 | [version]: http://contributor-covenant.org/version/1/4/ 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Smaine Milianni 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | help: ## Show this message 2 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 3 | 4 | phpcs: ## Run PHP CS Fixer 5 | ./vendor/bin/php-cs-fixer fix src 6 | ./vendor/bin/php-cs-fixer fix tests 7 | 8 | test: ## Run code tests 9 | ./vendor/bin/phpunit --testdox 10 | 11 | phpstan: 12 | ./vendor/bin/phpstan analyse src --level=9 13 | 14 | test-phpcs: ## Run coding standard tests 15 | ./vendor/bin/php-cs-fixer --diff --dry-run --using-cache=no -v fix src 16 | 17 | all: ## Run all DX tools 18 | all: phpcs phpstan test 19 | 20 | .PHONY: test test-phpcs phpstan 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Skeleton Bundle 2 | 3 | 🗺 The skeleton bundle is a skeleton to use when you want to create a open source bundle. 4 | 5 | ⚡️ Big thanks to [mtarld](https://github.com/mtarld) for the inspiration, anytime I create a bundle I see what is done in his library https://github.com/mtarld/api-platform-ms-bundle. 👀 6 | 7 | 💡 At some point, I decided to create a skeleton to avoid copy/paste and to have a base to start with. 8 | 9 | 🗣 You can clone this repository and remove the .git folder to start your own bundle. Obviously you should adapt the code to fit your needs. 10 | 11 | 🫵 If this skeleton is not up to date, please create an issue or a pull request to update it. 12 | 13 | 🤝 If this skeleton helped you, please give it a star and tell me on twitter [@SmaineDev](https://twitter.com/@SmaineDev) 14 | 15 | #### Table of contents 16 | - [Inside the skeleton](#Inside-the-skeleton) 17 | - [Create the README for the Bundle](#The-Foo-Bundle) 18 | - [Publishing the bundle on packagist](#Publishing-the-bundle-on-packagist) 19 | 20 | ----------------- 21 | 22 | # Inside-the-skeleton 23 | 24 | You'll find a: 25 | - `main.yaml.dist` file in the `.github/workflows` folder. You should remove the `.dist` extension to trigger the github action. 26 | - `Makefile` with some useful commands to run tests and quality tools. 27 | - `src` directory where the core bundle classes can live. 28 | - `FooBundle.php` with classic instructions to configure a bundle. 29 | - `services.php` for configuring the "static" bundle services. 30 | - `tests` folder with an AppKernel and a config file to setup a Symfony app in order to test the bundle. 31 | 32 | ----------------- 33 | 34 | # The Foo Bundle 35 | 36 | A Symfony Bundle to [explain the purpose of the bundle here]. 37 | 38 | ## Getting started 39 | ### Installation 40 | You can easily install [Foo] bundle by composer 41 | ``` 42 | $ composer require /foo-bundle 43 | ``` 44 | Then, bundle should be registered. Just verify that `config\bundles.php` is containing : 45 | ```php 46 | Namespace\FooBundle\FooBundle::class => ['all' => true], 47 | ``` 48 | 49 | ### Configuration 50 | Then, you should register it in the configuration (`config/packages/foo_lib.yaml`) : 51 | ```yaml 52 | # config/packages/foo_lib.yaml 53 | foo_lib: 54 | # required 55 | foo: 'bar' 56 | # optional 57 | baz: 58 | - 'qux' 59 | - 'quux' 60 | - 'quuz' 61 | ``` 62 | 63 | ### Usage 64 | 65 | You can register a new foo service with implementing `FooInterface` or adding a tag `foo_lib.foo` if you don't use the autoconfiguration. 66 | 67 | ```yaml 68 | # config/services.yaml 69 | services: 70 | # Register a new foo service 71 | Namespace\FooBundle\Foo: 72 | tags: ['foo_lib.foo'] 73 | ``` 74 | 75 | ```php 76 | class FooCustom implements FooInterface 77 | { 78 | public function foo(): string 79 | { 80 | return 'bar'; 81 | } 82 | } 83 | ``` 84 | 85 | ## Contributing 86 | Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. 87 | 88 | After writing your fix/feature, you can run following commands to make sure that everything is still ok. 89 | 90 | ```bash 91 | # Install dev dependencies 92 | $ composer install 93 | 94 | # Running tests and quality tools locally 95 | $ make all 96 | ``` 97 | 98 | ## Authors 99 | - John Doe - [JohnDoe](https://github.com/johndoe) - 100 | 101 | ----------------- 102 | 103 | ## Publishing the bundle to be used by other developers through composer 104 | 105 | 1- Create the release on the repository 106 | - Go to https://github.com/[pseudo]/[the-lib]/releases/new 107 | - "Choose a tag" read carefully the Tagging suggestions. 108 | 109 | 2- Create the package on packagist 110 | - Go to https://packagist.org/packages/submit 111 | - Enter the github repository url 112 | - Click on "Check" 113 | - Click on "Submit" 114 | - Make the package auto-updatable by clicking on "Enable auto-updates" so you don't have to do it manually each time you create a new release. 115 | 116 | 3- Create the Symfony Recipe to be able to use the bundle with Symfony Flex and configure the bundle directly with composer 117 | - Go to https://github.com/symfony/recipes-contrib/ 118 | - Fork the repository 119 | - Clone the repository and create a pull request with the recipe [like this](https://github.com/symfony/recipes-contrib/pull/1102/files) for your bundle. 120 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "project", 3 | "name": "name/foo-bundle", 4 | "description": "The place where you should describe your bundle", 5 | "license": "proprietary", 6 | "minimum-stability": "stable", 7 | "prefer-stable": true, 8 | "require": { 9 | "php": "^8.1.0", 10 | "symfony/console": "6.2.*" 11 | }, 12 | "require-dev": { 13 | "phpstan/phpstan": "^1.10", 14 | "phpunit/phpunit": "^9.5", 15 | "friendsofphp/php-cs-fixer": "^3.1", 16 | "symfony/browser-kit": "^6.2", 17 | "symfony/framework-bundle": "^6.2", 18 | "symfony/yaml": "^6.2" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Eniams\\FooBundle\\": "src/" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "Eniams\\FooBundle\\Tests\\": "tests/" 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | tests 20 | 21 | 22 | 23 | 24 | 25 | src 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/FooBundle.php: -------------------------------------------------------------------------------- 1 | rootNode() 22 | ->children() 23 | ->integerNode('client_id')->end() 24 | ->scalarNode('client_secret')->end() 25 | ->end() 26 | ->end() 27 | ->end() 28 | ; 29 | } 30 | 31 | public function loadExtension(array $configs, ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void 32 | { 33 | // Load the services.php file in the same bundle. 34 | $loader = new PhpFileLoader($containerBuilder, new FileLocator(__DIR__.'/Resources/config')); 35 | $loader->load('services.php'); 36 | 37 | // Get the configuration `client_id` `client_secret` set by the User who loads the bundle. 38 | $clientId = $configs['client_id']; 39 | $clientSecret = $configs['client_secret']; 40 | 41 | if ('' === $clientId || '' === $clientSecret) { 42 | throw new \InvalidArgumentException(sprintf('You must provide a valid client id and secret for twitter')); 43 | } 44 | 45 | // Create a service definition for the `FooService` class. 46 | // A service definition is a PHP object that contains all the configuration information about the service to create. 47 | $containerBuilder->setDefinition('eniams.foo.such_service', new Definition(FooService::class)) 48 | ->setArgument(0, $clientId) 49 | ->setArgument(1, $clientSecret) 50 | ; 51 | 52 | // Register the `FooInterface` interface for autoconfiguration. 53 | // So all classes that implement the interface `FooInterface::class` will be automatically tagged with `eniams.foo.tag`. 54 | $containerBuilder->registerForAutoconfiguration(FooInterface::class)->addTag('eniams.foo.tag'); 55 | 56 | // Create a service definition for the `DummyFactory` class. 57 | // Injected with all services tagged with `eniams.foo.tag`. 58 | $containerBuilder->setDefinition('eniams.foo.dummy_factory', new Definition(DummyFactory::class)) 59 | ->setArguments([tagged_iterator('eniams.foo.tag')]) 60 | ; 61 | 62 | // create a service definition for the `FooListener` class 63 | // that will be tagged with `kernel.event_subscriber` and 64 | // have a service injected: `eniams.foo.dummy_factory` 65 | $containerConfigurator 66 | ->services() 67 | ->set('eniams.foo.listener', FooListener::class) 68 | ->tag('kernel.event_subscriber') 69 | ->args([ 70 | new Reference('eniams.foo.dummy_factory'), 71 | ]) 72 | ; 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /src/Resources/config/services.php: -------------------------------------------------------------------------------- 1 | services() 7 | ->defaults() 8 | ->private() 9 | ->autowire() 10 | ->set('eniams.foo.such_service', FooService::class) 11 | ->tag('eniams.foo.tag') 12 | ; 13 | }; -------------------------------------------------------------------------------- /tests/App/AppKernel.php: -------------------------------------------------------------------------------- 1 | setParameter('kernel.project_dir', __DIR__); 27 | 28 | $loader->load(__DIR__.'/packages/config.yaml'); 29 | } 30 | } -------------------------------------------------------------------------------- /tests/App/Func/FooServiceTest.php: -------------------------------------------------------------------------------- 1 | get('eniams.foo.such_service'); 16 | $this->assertInstanceOf(FooService::class, $fooService); 17 | //... 18 | } 19 | } -------------------------------------------------------------------------------- /tests/App/Unit/FooFactoryTest.php: -------------------------------------------------------------------------------- 1 |