#!/usr/bin/env php find(); if (!$phpBin) { echo 'Php executable could not be found.'.PHP_EOL; } $options = getopt('i', array('install')); if (isset($options['i']) || isset($options['install'])) { install(); echo "Git hook successfully installed" . PHP_EOL; exit(1); } $options = getopt('u', array('uninstall')); if (isset($options['u']) || isset($options['uninstall'])) { uninstall(); echo "Git hook successfully uninstalled" . PHP_EOL; exit(1); } function install() { global $projectRootDir; uninstall(); //create link $link = $projectRootDir . '/.git/hooks/pre-commit'; exec(sprintf('ln -s %s %s', __FILE__, $link)); } function uninstall() { global $projectRootDir; //create link $link = $projectRootDir . '/.git/hooks/pre-commit'; @unlink($link); } function getFilesToFix() { $files = array(); exec('git diff-index --name-only --cached --diff-filter=ACMR HEAD --', $files); $stagedFiles = array_filter($files, function ($file) { return (bool) preg_match('/\.(php|twig|translations\/*.yml)$/', $file); }); $stagedFiles = array_filter($stagedFiles, function ($file) { return (bool) preg_match('/^pkg\//', $file); }); return $stagedFiles; } function runPhpLint() { global $phpBin, $projectRootDir; $output = []; foreach (getFilesToFix() as $file) { $commandOutput = null; $returnCode = null; exec(sprintf('%s -l %s', $phpBin, $projectRootDir.'/'.$file), $commandOutput, $returnCode); if ($returnCode) { $output[] = $commandOutput; } } return $output; } function runPhpCsFixer() { global $phpBin, $projectRootDir; $phpCsFixerBin = $projectRootDir . '/bin/php-cs-fixer'; if (!file_exists($phpCsFixerBin)) { echo $phpCsFixerBin.' File could not be found. Make sure you run command from project\'s root directory'.PHP_EOL; } $filesWithErrors = array(); $output = ''; $returnCode = null; exec(sprintf( '%s %s fix --config=.php_cs.php --dry-run --no-interaction --path-mode=intersection -- %s', $phpBin, $phpCsFixerBin, implode(' ', getFilesToFix()) ), $output, $returnCode); if ($returnCode) { exec(sprintf( '%s %s fix --config=.php_cs.php --no-interaction -v --path-mode=intersection -- %s', $phpBin, $phpCsFixerBin, implode(' ', getFilesToFix()) ), $output); } return $returnCode; } function runPhpstan() { $output = ''; $returnCode = null; exec(sprintf( 'docker run --workdir="/mqdev" -v "`pwd`:/mqdev" --rm enqueue/dev:latest php -d memory_limit=1024M bin/phpstan analyse -l 1 -c phpstan.neon %s', implode(' ', getFilesToFix()) ), $output, $returnCode); return $returnCode ? $output : false; } echo sprintf('Found %s staged files', count(getFilesToFix())).PHP_EOL; $phpSyntaxErrors = runPhpLint(); if ($phpSyntaxErrors) { echo "Php syntax errors were found in next files:" . PHP_EOL; foreach ($phpSyntaxErrors as $phpSyntaxErrors) { echo array_walk_recursive($phpSyntaxErrors, function($item) { echo $item.PHP_EOL; }) . PHP_EOL; } exit(1); } $phpCSFixed = runPhpCsFixer(); if ($phpCSFixed) { echo "Incorrect coding standards were detected and fixed." . PHP_EOL; echo "Please stash changes and run commit again." . PHP_EOL; exit(1); } $phpStanErrors = runPhpstan(); if ($phpStanErrors) { echo array_walk_recursive($phpStanErrors, function($item) { echo $item.PHP_EOL; }) . PHP_EOL; echo PHP_EOL; exit(1); } exit(0);