Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ Like what we do? Want to join us? Check out our job listings on our [career page
----
[BitBag](https://bitbag.io/) coding standard helps you produce solid and maintainable code.
At [BitBag Coding Bible](https://github.com/BitBagCommerce/BitBagBible) you can get familiar with standard we have
implemented in our library. [ECS](https://github.com/symplify/easy-coding-standard)
and [PHPStan](https://github.com/phpstan/phpstan) are responsible for keeping your code in order.
implemented in our library. [ECS](https://github.com/symplify/easy-coding-standard),
[PHPStan](https://github.com/phpstan/phpstan)
and [Twigcs](https://github.com/friendsoftwig/twigcs) are responsible for keeping your code in order.

## We are here to help
This **open-source library was developed to help the community**. If you have any additional questions, would like help with installing or configuring the plugin, or need any assistance with your project - let us know!
Expand Down Expand Up @@ -68,6 +69,23 @@ return static function (ContainerConfigurator $containerConfigurator): void {

```

For Twigcs create `.twig_cs.dist` file with the following lines
```php

<?php

declare(strict_types=1);

use BitBag\CodingStandard\Twigcs\Ruleset\Ruleset;
use FriendsOfTwig\Twigcs\Config\Config;

return Config::create()
->setName('bitbag_config')
->setRuleSet(Ruleset::class)
;

```


## Usage

Expand All @@ -79,6 +97,11 @@ If ECS found any standard violations, you can fix it by:
```bash
./vendor/bin/ecs check src --fix
```
To verify your Twig templates in /templates dir:
```bash
./vendor/bin/twigcs templates
```

## Customization

#### ECS
Expand All @@ -98,6 +121,23 @@ You can set PHPStan rule level with following commands
./vendor/bin/phpstan analyze --configuration=vendor/bitbag/coding-standard/phpstan.neon tests --level=5
```

#### Twigcs
You can set path to your Twig templates in the configuration file so you don't have to provide it in the twigcs command
```php
<?php

declare(strict_types=1);

use BitBag\CodingStandard\Twigcs\Ruleset\Ruleset;
use FriendsOfTwig\Twigcs\Config\Config;
use FriendsOfTwig\Twigcs\Finder\TemplateFinder;

return Config::create()
->setName('bitbag_config')
->setRuleSet(Ruleset::class)
->addFinder(TemplateFinder::create()->in(__DIR__.'/templates'))
;
```

# About us

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"phpstan/phpstan-webmozart-assert": "^1.0",
"symplify/easy-coding-standard": "^8.3 || ^9.4 || ^10.0 || ^11.0",
"friendsofphp/php-cs-fixer": "^3.0",
"slevomat/coding-standard": "^7.0"
"slevomat/coding-standard": "^7.0",
"friendsoftwig/twigcs": "^6.0"
},
"autoload": {
"psr-4": {
Expand Down
60 changes: 60 additions & 0 deletions src/Twigcs/Dto/HtmlTagDto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on hello@bitbag.io.
*/

declare(strict_types=1);

namespace BitBag\CodingStandard\Twigcs\Dto;

final class HtmlTagDto
{
/** @var string */
private $tag = '';

/** @var string */
private $html = '';

/** @var int */
private $offset = 0;

public function getTag(): string
{
return $this->tag;
}

public function setTag(string $tag): self
{
$this->tag = $tag;

return $this;
}

public function getHtml(): string
{
return $this->html;
}

public function setHtml(string $html): self
{
$this->html = $html;

return $this;
}

public function getOffset(): int
{
return $this->offset;
}

public function setOffset(int $offset): self
{
$this->offset = $offset;

return $this;
}
}
45 changes: 45 additions & 0 deletions src/Twigcs/Dto/OffsetDto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on hello@bitbag.io.
*/

declare(strict_types=1);

namespace BitBag\CodingStandard\Twigcs\Dto;

final class OffsetDto
{
/** @var int */
private $line = 0;

/** @var int */
private $column = 0;

public function getLine(): int
{
return $this->line;
}

public function setLine(int $line): self
{
$this->line = $line;

return $this;
}

public function getColumn(): int
{
return $this->column;
}

public function setColumn(int $column): self
{
$this->column = $column;

return $this;
}
}
69 changes: 69 additions & 0 deletions src/Twigcs/Rule/EmptyLinesRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on hello@bitbag.io.
*/

declare(strict_types=1);

namespace BitBag\CodingStandard\Twigcs\Rule;

use BitBag\CodingStandard\Twigcs\Ruleset\Ruleset;
use BitBag\CodingStandard\Twigcs\Util\HtmlUtil;
use FriendsOfTwig\Twigcs\Rule\AbstractRule;
use FriendsOfTwig\Twigcs\Rule\RuleInterface;
use FriendsOfTwig\Twigcs\TwigPort\TokenStream;

final class EmptyLinesRule extends AbstractRule implements RuleInterface
{
/** @var string */
private $pattern = '#(?<offset>\n{3,})#s';

/** @var HtmlUtil */
private $htmlUtil;

/** @var int */
private $lineNumberOffset = 2;

public function __construct($severity, HtmlUtil $htmlUtil)
{
parent::__construct($severity);

$this->htmlUtil = $htmlUtil;
}

public function check(TokenStream $tokens)
{
$violations = [];

$content = str_replace("\r", '', $tokens->getSourceContext()->getCode());
$this->htmlUtil->stripUnnecessaryTagsAndSavePositions($content);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the "and" in method tells us, it's not SRP friendly ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential SRP break


foreach ($this->getMultiLines($content) as $multiline) {
if ($this->htmlUtil->isInsideUnnecessaryTag($multiline['offset'][1])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the HtmlUtil class is too generic for "UnnecessaryTag". What does mean the "UnnecessaryTag"?

continue;
}

$offset = $this->htmlUtil->getTwigcsOffset($content, $multiline['offset'][1] + $this->lineNumberOffset);

$violations[] = $this->createViolation(
$tokens->getSourceContext()->getPath(),
$offset->getLine(),
0,
Ruleset::ERROR_MULTIPLE_EMPTY_LINES
);
}

return $violations;
}

private function getMultiLines(string $content): array
{
return preg_match_all($this->pattern, $content, $multilines, HtmlUtil::REGEX_FLAGS)
? $multilines
: [];
}
}
62 changes: 62 additions & 0 deletions src/Twigcs/Rule/Html/ApostropheInAttributesRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on hello@bitbag.io.
*/

declare(strict_types=1);

namespace BitBag\CodingStandard\Twigcs\Rule\Html;

use BitBag\CodingStandard\Twigcs\Ruleset\Ruleset;
use BitBag\CodingStandard\Twigcs\Util\HtmlUtil;
use FriendsOfTwig\Twigcs\Rule\AbstractRule;
use FriendsOfTwig\Twigcs\Rule\RuleInterface;
use FriendsOfTwig\Twigcs\TwigPort\TokenStream;

final class ApostropheInAttributesRule extends AbstractRule implements RuleInterface
{
/** @var string */
private $pattern = "#=\s*(?<offset>')#";

/** @var HtmlUtil */
private $htmlUtil;

public function __construct($severity, HtmlUtil $htmlUtil)
{
parent::__construct($severity);

$this->htmlUtil = $htmlUtil;
}

public function check(TokenStream $tokens)
{
$violations = [];
$content = $this->htmlUtil->stripUnnecessaryTagsAndSavePositions($tokens->getSourceContext()->getCode());

foreach ($this->htmlUtil->getParsedHtmlTags($content) as $tag) {
foreach ($this->getApostrophes($tag->getHtml()) as $apostrophe) {
$offset = $this->htmlUtil->getTwigcsOffset($content, $tag->getOffset() + $apostrophe['offset'][1]);

$violations[] = $this->createViolation(
$tokens->getSourceContext()->getPath(),
$offset->getLine(),
$offset->getColumn(),
sprintf(Ruleset::ERROR_APOSTROPHE_IN_ATTRIBUTE, $tag->getTag())
);
}
}

return $violations;
}

private function getApostrophes(string $html): array
{
return preg_match_all($this->pattern, $html, $quotes, HtmlUtil::REGEX_FLAGS)
? $quotes
: [];
}
}
62 changes: 62 additions & 0 deletions src/Twigcs/Rule/Html/MultiWhitespaceInAttributesRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on hello@bitbag.io.
*/

declare(strict_types=1);

namespace BitBag\CodingStandard\Twigcs\Rule\Html;

use BitBag\CodingStandard\Twigcs\Ruleset\Ruleset;
use BitBag\CodingStandard\Twigcs\Util\HtmlUtil;
use FriendsOfTwig\Twigcs\Rule\AbstractRule;
use FriendsOfTwig\Twigcs\Rule\RuleInterface;
use FriendsOfTwig\Twigcs\TwigPort\TokenStream;

final class MultiWhitespaceInAttributesRule extends AbstractRule implements RuleInterface
{
/** @var string */
private $pattern = '#(?<offset>\s{2,})#';

/** @var HtmlUtil */
private $htmlUtil;

public function __construct($severity, HtmlUtil $htmlUtil)
{
parent::__construct($severity);

$this->htmlUtil = $htmlUtil;
}

public function check(TokenStream $tokens)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason of not having return types in the check method?

{
$violations = [];
$content = $this->htmlUtil->stripUnnecessaryTagsAndSavePositions($tokens->getSourceContext()->getCode());

foreach ($this->htmlUtil->getParsedHtmlTags($content) as $tag) {
foreach ($this->getMultiSpaces($tag->getHtml()) as $space) {
$offset = $this->htmlUtil->getTwigcsOffset($content, $tag->getOffset() + $space['offset'][1]);

$violations[] = $this->createViolation(
$tokens->getSourceContext()->getPath(),
$offset->getLine(),
$offset->getColumn(),
sprintf(Ruleset::ERROR_MULTIPLE_WHITESPACES, $tag->getTag())
);
}
}

return $violations;
}

private function getMultiSpaces(string $html): array
{
return preg_match_all($this->pattern, $html, $spaces, HtmlUtil::REGEX_FLAGS)
? $spaces
: [];
}
}
Loading