Skip to content

Commit

Permalink
Merge pull request #6 from malukenho/enhancement/#5-allow-regex
Browse files Browse the repository at this point in the history
Allow regex match
  • Loading branch information
Jefersson Nathan committed Nov 16, 2016
2 parents 64137b8 + fa56c48 commit 28d4c3a
Show file tree
Hide file tree
Showing 18 changed files with 584 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .travis.coverage.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -x
if [ "$TRAVIS_PHP_VERSION" = '7.0' ] ; then
if [ "$TRAVIS_PHP_VERSION" = '5.6' ] ; then
./vendor/bin/phpunit --disallow-test-output --report-useless-tests --coverage-clover ./clover.xml
wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover ./clover.xml
Expand Down
16 changes: 16 additions & 0 deletions README.md
Expand Up @@ -44,6 +44,8 @@ and then run the checker:

So, you get errors or a message saying that everything is ok!

# Current year placeholder

You can also put `%year%` on your `.docheader` file to refer to the current
Year, like that:

Expand All @@ -52,3 +54,17 @@ Year, like that:
* @copyright Copyright (c) 2005-%year% Zend Technologies USA Inc. (http://www.zend.com)
*/
```

# Regex assertion

If you're using `>=0.1.5` version, you can use the `%regex:%` placeholder to match some content.

Example:

```php
/**
* @copyright Copyright (c) 20%regex:\d{2}%-2016 Zend Technologies USA Inc. (http://www.zend.com)
*/
```

In this case `%regex:\d{2}%` assert that it should be a number of two digits between `20` and `-`.
5 changes: 2 additions & 3 deletions bin/docheader
Expand Up @@ -37,9 +37,8 @@ if (! is_file('.docheader')) {
throw \DocHeader\Command\Exception\DocHeaderFileConfiguration::notFound();
}

// TODO: Create a way to apply filters
$header = str_replace('%year%', date('Y'), file_get_contents('.docheader'));
$filters = new DocHeader\Filter\Filter(file_get_contents('.docheader'));

$application = new Application();
$application->add(new \DocHeader\Command\Checker(null, $header));
$application->add(new \DocHeader\Command\Checker(null, $filters->applyFilters()));
$application->run();
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Expand Up @@ -19,7 +19,7 @@
<directory suffix=".phpt">./tests/functional</directory>
</testsuite>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<whitelist>
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
Expand Down
15 changes: 12 additions & 3 deletions src/Command/Checker.php
Expand Up @@ -17,7 +17,8 @@
*/
namespace DocHeader\Command;

use DocHeader\Helper\FileResolve;
use DocHeader\Helper\IOResourcePathResolution;
use DocHeader\Validator\RegExp;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -52,12 +53,13 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
$directory = $input->getArgument('directory');
$finder = (new FileResolve($directory))->__invoke();
$finder = (new IOResourcePathResolution($directory))->__invoke();
$validator = new RegExp($this->header);

/* @var $file \Symfony\Component\Finder\SplFileInfo */
foreach ($finder as $directory) {
foreach ($directory as $file) {
if (!strpos($file->getContents(), $this->header)) {
if ($this->docIsNotCompatible($validator, $file->getContents())) {
defined('FAILED') ?: define('FAILED', 1);
$output->writeln('-> ' . $file->getRelativePathname());
}
Expand All @@ -73,4 +75,11 @@ protected function execute(InputInterface $input, OutputInterface $output)

$output->writeln('<bg=green;fg=white> Everything is OK! </>');
}

private function docIsNotCompatible($headerValidator, $fileContent)
{
return (! $headerValidator->__invoke($fileContent)
&& false === strpos($fileContent, $this->header)
) || false === strpos($fileContent, $this->header);
}
}
4 changes: 4 additions & 0 deletions src/Command/Exception/DirectoryException.php
Expand Up @@ -15,8 +15,12 @@
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/

namespace DocHeader\Command\Exception;

/**
* @author Jefersson Nathan <malukenho@phpse.net>
*/
final class DirectoryException extends \Exception
{
public static function notFound($directory)
Expand Down
3 changes: 3 additions & 0 deletions src/Command/Exception/DocHeaderFileConfiguration.php
Expand Up @@ -17,6 +17,9 @@
*/
namespace DocHeader\Command\Exception;

/**
* @author Jefersson Nathan <malukenho@phpse.net>
*/
final class DocHeaderFileConfiguration extends \Exception
{
public static function notFound()
Expand Down
56 changes: 56 additions & 0 deletions src/Filter/Filter.php
@@ -0,0 +1,56 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/
namespace DocHeader\Filter;

/**
* @author Jefersson Nathan <malukenho@phpse.net>
* @license MIT
*/
final class Filter
{
/**
* @var string
*/
private $docheader;

private $dockBlockDefaultFilters = [
ReplaceCurrentYearPlaceholder::class,
];

/**
* @param string $docheader
*/
public function __construct($docheader)
{
$this->docheader = $docheader;
}

/**
* @return string
*/
public function applyFilters()
{
$docheader = $this->docheader;

foreach ($this->dockBlockDefaultFilters as $filterName) {
$docheader = (new $filterName)->__invoke($docheader);
}

return $docheader;
}
}
35 changes: 35 additions & 0 deletions src/Filter/FilterInterface.php
@@ -0,0 +1,35 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/
namespace DocHeader\Filter;

/**
* @author Jefersson Nathan <malukenho@phpse.net>
* @license MIT
*/
interface FilterInterface
{
/**
* Receives the docheader content, may already processed by other
* filter and apply some changes, them return it.
*
* @param string $docheader
*
* @return string
*/
public function __invoke($docheader);
}
36 changes: 36 additions & 0 deletions src/Filter/ReplaceCurrentYearPlaceholder.php
@@ -0,0 +1,36 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/

namespace DocHeader\Filter;

/**
* @author Jefersson Nathan <malukenho@phpse.net>
* @license MIT
*/
final class ReplaceCurrentYearPlaceholder implements FilterInterface
{
const CURRENT_YEAR = '%year%';

/**
* {@inheritDoc}
*/
public function __invoke($docheader)
{
return str_replace(self::CURRENT_YEAR, date('Y'), $docheader);
}
}
Expand Up @@ -23,7 +23,7 @@
* @author Jefersson Nathan <malukenho@phpse.net>
* @license MIT
*/
final class FileResolve
final class IOResourcePathResolution
{
/**
* @var string
Expand Down
76 changes: 76 additions & 0 deletions src/Validator/RegExp.php
@@ -0,0 +1,76 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/

namespace DocHeader\Validator;

/**
* @author Jefersson Nathan <malukenho@phpse.net>
* @license MIT
*/
final class RegExp
{
const TAG_BEGIN = '%regexp:';
const TAG_END = '%';

/**
* @var string
*/
private $pattern;

/**
* @param string $pattern
*/
public function __construct($pattern)
{
$this->pattern = $pattern;
}

/**
* {@inheritDoc}
*/
public function __invoke($docheader)
{
$didMatch = preg_match_all(
'{' . preg_quote(self::TAG_BEGIN) . '(.+?)' . preg_quote(self::TAG_END) . '}',
$this->pattern,
$matches
);

if (! $didMatch) {
// In case of not have any regexp to match
// just return true
return true;
}

$matchable = $this->pattern;

/* @var $matches array[] */
foreach ($matches[0] as $k => $match) {
$matchable = str_replace($match, sha1($match . $k), $matchable);
}

$protected = preg_quote($matchable);

/* @var $matches array[] */
foreach ($matches[1] as $k => $match) {
$protected = str_replace(preg_quote(sha1($matches[0][$k] . $k)), $match, $protected);
}

return (bool) preg_match('#' . $protected . '#', $docheader);
}
}
50 changes: 50 additions & 0 deletions tests/unit/Command/Exception/DirectoryExceptionTest.php
@@ -0,0 +1,50 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/
namespace DocHeaderTest\Command\Exception;

use DocHeader\Command\Exception\DirectoryException;

/**
* Tests for {@see \DocHeader\Command\Exception\DirectoryException}.
*
* @group Unitary
* @author Jefersson Nathan <malukenho@phpse.net>
* @license MIT
*
* @covers \DocHeader\Command\Exception\DirectoryException
*/
final class DirectoryExceptionTest extends \PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function it_should_throw_exception_for_directory_not_found()
{
$sut = DirectoryException::notFound('foo');

$this->assertInstanceOf(DirectoryException::class, $sut);
$this->assertSame(
'Directory "foo" could not be found.',
$sut->getMessage()
);

$this->setExpectedException(DirectoryException::class);

throw $sut;
}
}

0 comments on commit 28d4c3a

Please sign in to comment.