Nette Documentation Preview

syntax
Preset a balík
**************

.[perex]
Jak zabalit vlastní pravidla a styl do presetu a extension, distribuovat je přes Composer a nechat uživatele zapnout je jedním řádkem.


Preset
======

Preset je třída s atributem `#[PresetInfo]`, která vrátí seznam pravidel s volbami a může vycházet z jiných presetů:

```php
namespace Acme\CodeStyle;

use DressCode\Preset;
use DressCode\PresetContext;
use DressCode\PresetInfo;
use DressCode\Presets\Per;

#[PresetInfo('acme/house', 'The Acme house style', indent: "\t", eol: "\n")]
final class HousePreset implements Preset
{
	public function getRules(PresetContext $context): array
	{
		return [
			'dresscode/ordered-imports' => true,
			'dresscode/line-length' => ['limit' => 100],
			'dresscode/no-alternative-syntax' => false,
			ExceptionMessagePeriodRule::class => true,
			'dresscode/octal-notation' => $context->getPhpVersion()->isAtLeast('8.1'),
		];
	}


	public function getParents(): array
	{
		return [Per::class];
	}
}
```

- Rodiče se použijí napřed; potomek přepisuje celé položky, takže volby se nikdy neslučují. Pořadí pravidel je pořadí první zmínky.
- Vestavěná pravidla lze uvést jménem, vlastní názvem třídy; jméno vlastního pravidla se zaregistruje při první zmínce.
- Hodnota může být `true`, `false`, mapa voleb, nebo továrna `fn(): Rule` pro pravidlo se závislostmi.
- `indent` a `eol` v `PresetInfo` je styl, který preset předpokládá; konfigurace ho může přepsat.

Poslední řádek ukázky není potřeba: pravidlo s `minPhpVersion` se pod svou verzí vynechá samo. `PresetContext` se hodí, když má preset pod různými verzemi PHP zapínat různá pravidla nebo volby.

Preset zapnete názvem třídy, dokud nemá extension, která ho zaregistruje jménem:

```neon
presets:
	- Acme\CodeStyle\HousePreset
```


Extension
=========

Extension je to, co balíček dodá místo konfiguračního souboru: invokable třída, která dostane prázdný `Config` a nastaví do něj, co uzná za vhodné. Tak vypadá extension Nette Coding Standardu:

```php
namespace Nette\CodingStandard;

use DressCode\Config;

final class Extension
{
	public function __invoke(Config $config): void
	{
		$config
			->registerPresets([Presets\Php::class, Presets\CleanCode::class, Presets\OptimizeFn::class, Presets\Types::class])
			->preset('nette/php')
			->excludePaths(['expected', 'tmp', 'fixtures*'])
			->skipWhen(PhpVersionFilter::create());
	}
}
```

Uživatel ji zapne jedním řádkem a dál pracuje se jmény, která zaregistrovala:

```neon
extensions:
	- Nette\CodingStandard\Extension

presets:
	- nette/clean-code
```

Extension může nastavit cokoli, co umí `Config`: registrovat pravidla (`registerRules()`) a presety (`registerPresets()`), zapnout preset, přidat vyloučené cesty, přípony souborů, `skipWhen` podle obsahu, analýzu s továrnou. Všechno, co nastaví, je vrstva **pod** konfigurací projektu: projekt cokoli z toho přepíše, s výjimkou vyloučených cest, které se jen sčítají. Pořadí, v jakém se extensions v konfiguraci uvádějí, nehraje roli; extension, kterou zapne jiná extension, se použije jednou.

Closures patří sem, ne do NEONu: `skipWhen`, továrna pravidla se závislostmi, továrna analýzy. NEON deklaruje, extension implementuje.


Balíček
=======

Balíček s presetem nebo pravidly je obyčejný Composer balíček, který požaduje `dresscode/dresscode` a sdílí s projektem autoloader:

```json
{
	"name": "acme/code-style",
	"require": {
		"dresscode/dresscode": "^1.0"
	},
	"autoload": {
		"psr-4": {"Acme\\CodeStyle\\": "src/"}
	}
}
```

Uvnitř třídy pravidel, presety, extension a fixtury s testy. Jména pravidel nesou vendor balíčku (`acme/…`), aby se nesrazila s jinými. Kdo chce, aby uživatel po `composer require` nemusel psát ani řádek `extensions`, přidá do `composer.json` balíčku hint, podle kterého DressCode extension najde sám:

```json
{
	"extra": {
		"dresscode": {
			"extensions": ["Acme\\CodeStyle\\Extension"]
		}
	}
}
```

Automaticky nalezená extension se chová stejně jako zapsaná; `dresscode rules` u každého pravidla řekne, odkud přišlo.

Preset a balík

Jak zabalit vlastní pravidla a styl do presetu a extension, distribuovat je přes Composer a nechat uživatele zapnout je jedním řádkem.

Preset

Preset je třída s atributem #[PresetInfo], která vrátí seznam pravidel s volbami a může vycházet z jiných presetů:

namespace Acme\CodeStyle;

use DressCode\Preset;
use DressCode\PresetContext;
use DressCode\PresetInfo;
use DressCode\Presets\Per;

#[PresetInfo('acme/house', 'The Acme house style', indent: "\t", eol: "\n")]
final class HousePreset implements Preset
{
	public function getRules(PresetContext $context): array
	{
		return [
			'dresscode/ordered-imports' => true,
			'dresscode/line-length' => ['limit' => 100],
			'dresscode/no-alternative-syntax' => false,
			ExceptionMessagePeriodRule::class => true,
			'dresscode/octal-notation' => $context->getPhpVersion()->isAtLeast('8.1'),
		];
	}


	public function getParents(): array
	{
		return [Per::class];
	}
}
  • Rodiče se použijí napřed; potomek přepisuje celé položky, takže volby se nikdy neslučují. Pořadí pravidel je pořadí první zmínky.
  • Vestavěná pravidla lze uvést jménem, vlastní názvem třídy; jméno vlastního pravidla se zaregistruje při první zmínce.
  • Hodnota může být true, false, mapa voleb, nebo továrna fn(): Rule pro pravidlo se závislostmi.
  • indent a eol v PresetInfo je styl, který preset předpokládá; konfigurace ho může přepsat.

Poslední řádek ukázky není potřeba: pravidlo s minPhpVersion se pod svou verzí vynechá samo. PresetContext se hodí, když má preset pod různými verzemi PHP zapínat různá pravidla nebo volby.

Preset zapnete názvem třídy, dokud nemá extension, která ho zaregistruje jménem:

presets:
	- Acme\CodeStyle\HousePreset

Extension

Extension je to, co balíček dodá místo konfiguračního souboru: invokable třída, která dostane prázdný Config a nastaví do něj, co uzná za vhodné. Tak vypadá extension Nette Coding Standardu:

namespace Nette\CodingStandard;

use DressCode\Config;

final class Extension
{
	public function __invoke(Config $config): void
	{
		$config
			->registerPresets([Presets\Php::class, Presets\CleanCode::class, Presets\OptimizeFn::class, Presets\Types::class])
			->preset('nette/php')
			->excludePaths(['expected', 'tmp', 'fixtures*'])
			->skipWhen(PhpVersionFilter::create());
	}
}

Uživatel ji zapne jedním řádkem a dál pracuje se jmény, která zaregistrovala:

extensions:
	- Nette\CodingStandard\Extension

presets:
	- nette/clean-code

Extension může nastavit cokoli, co umí Config: registrovat pravidla (registerRules()) a presety (registerPresets()), zapnout preset, přidat vyloučené cesty, přípony souborů, skipWhen podle obsahu, analýzu s továrnou. Všechno, co nastaví, je vrstva pod konfigurací projektu: projekt cokoli z toho přepíše, s výjimkou vyloučených cest, které se jen sčítají. Pořadí, v jakém se extensions v konfiguraci uvádějí, nehraje roli; extension, kterou zapne jiná extension, se použije jednou.

Closures patří sem, ne do NEONu: skipWhen, továrna pravidla se závislostmi, továrna analýzy. NEON deklaruje, extension implementuje.

Balíček

Balíček s presetem nebo pravidly je obyčejný Composer balíček, který požaduje dresscode/dresscode a sdílí s projektem autoloader:

{
	"name": "acme/code-style",
	"require": {
		"dresscode/dresscode": "^1.0"
	},
	"autoload": {
		"psr-4": {"Acme\\CodeStyle\\": "src/"}
	}
}

Uvnitř třídy pravidel, presety, extension a fixtury s testy. Jména pravidel nesou vendor balíčku (acme/…), aby se nesrazila s jinými. Kdo chce, aby uživatel po composer require nemusel psát ani řádek extensions, přidá do composer.json balíčku hint, podle kterého DressCode extension najde sám:

{
	"extra": {
		"dresscode": {
			"extensions": ["Acme\\CodeStyle\\Extension"]
		}
	}
}

Automaticky nalezená extension se chová stejně jako zapsaná; dresscode rules u každého pravidla řekne, odkud přišlo.