Missing dependancies
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Andreas Möller <am@localheinz.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Cache implements CacheInterface
|
||||
{
|
||||
private SignatureInterface $signature;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private array $hashes = [];
|
||||
|
||||
public function __construct(SignatureInterface $signature)
|
||||
{
|
||||
$this->signature = $signature;
|
||||
}
|
||||
|
||||
public function getSignature(): SignatureInterface
|
||||
{
|
||||
return $this->signature;
|
||||
}
|
||||
|
||||
public function has(string $file): bool
|
||||
{
|
||||
return \array_key_exists($file, $this->hashes);
|
||||
}
|
||||
|
||||
public function get(string $file): ?string
|
||||
{
|
||||
if (!$this->has($file)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->hashes[$file];
|
||||
}
|
||||
|
||||
public function set(string $file, string $hash): void
|
||||
{
|
||||
$this->hashes[$file] = $hash;
|
||||
}
|
||||
|
||||
public function clear(string $file): void
|
||||
{
|
||||
unset($this->hashes[$file]);
|
||||
}
|
||||
|
||||
public function toJson(): string
|
||||
{
|
||||
$json = json_encode([
|
||||
'php' => $this->getSignature()->getPhpVersion(),
|
||||
'version' => $this->getSignature()->getFixerVersion(),
|
||||
'indent' => $this->getSignature()->getIndent(),
|
||||
'lineEnding' => $this->getSignature()->getLineEnding(),
|
||||
'rules' => $this->getSignature()->getRules(),
|
||||
'hashes' => $this->hashes,
|
||||
]);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \UnexpectedValueException(sprintf(
|
||||
'Cannot encode cache signature to JSON, error: "%s". If you have non-UTF8 chars in your signature, like in license for `header_comment`, consider enabling `ext-mbstring` or install `symfony/polyfill-mbstring`.',
|
||||
json_last_error_msg()
|
||||
));
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function fromJson(string $json): self
|
||||
{
|
||||
$data = json_decode($json, true);
|
||||
|
||||
if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'Value needs to be a valid JSON string, got "%s", error: "%s".',
|
||||
$json,
|
||||
json_last_error_msg()
|
||||
));
|
||||
}
|
||||
|
||||
$requiredKeys = [
|
||||
'php',
|
||||
'version',
|
||||
'indent',
|
||||
'lineEnding',
|
||||
'rules',
|
||||
'hashes',
|
||||
];
|
||||
|
||||
$missingKeys = array_diff_key(array_flip($requiredKeys), $data);
|
||||
|
||||
if (\count($missingKeys) > 0) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'JSON data is missing keys "%s"',
|
||||
implode('", "', $missingKeys)
|
||||
));
|
||||
}
|
||||
|
||||
$signature = new Signature(
|
||||
$data['php'],
|
||||
$data['version'],
|
||||
$data['indent'],
|
||||
$data['lineEnding'],
|
||||
$data['rules']
|
||||
);
|
||||
|
||||
$cache = new self($signature);
|
||||
|
||||
$cache->hashes = array_map(function ($v): string {
|
||||
// before v3.11.1 the hashes were crc32 encoded and saved as integers
|
||||
// @TODO: remove the to string cast/array_map in v4.0
|
||||
return \is_int($v) ? (string) $v : $v;
|
||||
}, $data['hashes']);
|
||||
|
||||
return $cache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Andreas Möller <am@localheinz.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface CacheInterface
|
||||
{
|
||||
public function getSignature(): SignatureInterface;
|
||||
|
||||
public function has(string $file): bool;
|
||||
|
||||
public function get(string $file): ?string;
|
||||
|
||||
public function set(string $file, string $hash): void;
|
||||
|
||||
public function clear(string $file): void;
|
||||
|
||||
public function toJson(): string;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface CacheManagerInterface
|
||||
{
|
||||
public function needFixing(string $file, string $fileContent): bool;
|
||||
|
||||
public function setFile(string $file, string $fileContent): void;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Directory implements DirectoryInterface
|
||||
{
|
||||
private string $directoryName;
|
||||
|
||||
public function __construct(string $directoryName)
|
||||
{
|
||||
$this->directoryName = $directoryName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelativePathTo(string $file): string
|
||||
{
|
||||
$file = $this->normalizePath($file);
|
||||
|
||||
if (
|
||||
'' === $this->directoryName
|
||||
|| 0 !== stripos($file, $this->directoryName.\DIRECTORY_SEPARATOR)
|
||||
) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return substr($file, \strlen($this->directoryName) + 1);
|
||||
}
|
||||
|
||||
private function normalizePath(string $path): string
|
||||
{
|
||||
return str_replace(['\\', '/'], \DIRECTORY_SEPARATOR, $path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*/
|
||||
interface DirectoryInterface
|
||||
{
|
||||
public function getRelativePathTo(string $file): string;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* Class supports caching information about state of fixing files.
|
||||
*
|
||||
* Cache is supported only for phar version and version installed via composer.
|
||||
*
|
||||
* File will be processed by PHP CS Fixer only if any of the following conditions is fulfilled:
|
||||
* - cache is corrupt
|
||||
* - fixer version changed
|
||||
* - rules changed
|
||||
* - file is new
|
||||
* - file changed
|
||||
*
|
||||
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class FileCacheManager implements CacheManagerInterface
|
||||
{
|
||||
private FileHandlerInterface $handler;
|
||||
|
||||
private SignatureInterface $signature;
|
||||
|
||||
private bool $isDryRun;
|
||||
|
||||
private DirectoryInterface $cacheDirectory;
|
||||
|
||||
/**
|
||||
* @var CacheInterface
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
public function __construct(
|
||||
FileHandlerInterface $handler,
|
||||
SignatureInterface $signature,
|
||||
bool $isDryRun = false,
|
||||
?DirectoryInterface $cacheDirectory = null
|
||||
) {
|
||||
$this->handler = $handler;
|
||||
$this->signature = $signature;
|
||||
$this->isDryRun = $isDryRun;
|
||||
$this->cacheDirectory = $cacheDirectory ?? new Directory('');
|
||||
|
||||
$this->readCache();
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->writeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is not intended to be serialized,
|
||||
* and cannot be deserialized (see __wakeup method).
|
||||
*/
|
||||
public function __sleep(): array
|
||||
{
|
||||
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the deserialization of the class to prevent attacker executing
|
||||
* code by leveraging the __destruct method.
|
||||
*
|
||||
* @see https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection
|
||||
*/
|
||||
public function __wakeup(): void
|
||||
{
|
||||
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
||||
}
|
||||
|
||||
public function needFixing(string $file, string $fileContent): bool
|
||||
{
|
||||
$file = $this->cacheDirectory->getRelativePathTo($file);
|
||||
|
||||
return !$this->cache->has($file) || $this->cache->get($file) !== $this->calcHash($fileContent);
|
||||
}
|
||||
|
||||
public function setFile(string $file, string $fileContent): void
|
||||
{
|
||||
$file = $this->cacheDirectory->getRelativePathTo($file);
|
||||
|
||||
$hash = $this->calcHash($fileContent);
|
||||
|
||||
if ($this->isDryRun && $this->cache->has($file) && $this->cache->get($file) !== $hash) {
|
||||
$this->cache->clear($file);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cache->set($file, $hash);
|
||||
}
|
||||
|
||||
private function readCache(): void
|
||||
{
|
||||
$cache = $this->handler->read();
|
||||
|
||||
if (null === $cache || !$this->signature->equals($cache->getSignature())) {
|
||||
$cache = new Cache($this->signature);
|
||||
}
|
||||
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
private function writeCache(): void
|
||||
{
|
||||
$this->handler->write($this->cache);
|
||||
}
|
||||
|
||||
private function calcHash(string $content): string
|
||||
{
|
||||
return md5($content);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
|
||||
/**
|
||||
* @author Andreas Möller <am@localheinz.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class FileHandler implements FileHandlerInterface
|
||||
{
|
||||
private string $file;
|
||||
|
||||
public function __construct(string $file)
|
||||
{
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
public function getFile(): string
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function read(): ?CacheInterface
|
||||
{
|
||||
if (!file_exists($this->file)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->file);
|
||||
|
||||
try {
|
||||
$cache = Cache::fromJson($content);
|
||||
} catch (\InvalidArgumentException $exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $cache;
|
||||
}
|
||||
|
||||
public function write(CacheInterface $cache): void
|
||||
{
|
||||
$content = $cache->toJson();
|
||||
|
||||
if (file_exists($this->file)) {
|
||||
if (is_dir($this->file)) {
|
||||
throw new IOException(
|
||||
sprintf('Cannot write cache file "%s" as the location exists as directory.', realpath($this->file)),
|
||||
0,
|
||||
null,
|
||||
$this->file
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_writable($this->file)) {
|
||||
throw new IOException(
|
||||
sprintf('Cannot write to file "%s" as it is not writable.', realpath($this->file)),
|
||||
0,
|
||||
null,
|
||||
$this->file
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$dir = \dirname($this->file);
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
throw new IOException(
|
||||
sprintf('Directory of cache file "%s" does not exists.', $this->file),
|
||||
0,
|
||||
null,
|
||||
$this->file
|
||||
);
|
||||
}
|
||||
|
||||
@touch($this->file);
|
||||
@chmod($this->file, 0666);
|
||||
}
|
||||
|
||||
$bytesWritten = @file_put_contents($this->file, $content);
|
||||
|
||||
if (false === $bytesWritten) {
|
||||
$error = error_get_last();
|
||||
|
||||
throw new IOException(
|
||||
sprintf('Failed to write file "%s", "%s".', $this->file, $error['message'] ?? 'no reason available'),
|
||||
0,
|
||||
null,
|
||||
$this->file
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Andreas Möller <am@localheinz.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface FileHandlerInterface
|
||||
{
|
||||
public function getFile(): string;
|
||||
|
||||
public function read(): ?CacheInterface;
|
||||
|
||||
public function write(CacheInterface $cache): void;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Andreas Möller <am@localheinz.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class NullCacheManager implements CacheManagerInterface
|
||||
{
|
||||
public function needFixing(string $file, string $fileContent): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setFile(string $file, string $fileContent): void
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Andreas Möller <am@localheinz.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Signature implements SignatureInterface
|
||||
{
|
||||
private string $phpVersion;
|
||||
|
||||
private string $fixerVersion;
|
||||
|
||||
private string $indent;
|
||||
|
||||
private string $lineEnding;
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, mixed>|bool>
|
||||
*/
|
||||
private array $rules;
|
||||
|
||||
/**
|
||||
* @param array<string, array<string, mixed>|bool> $rules
|
||||
*/
|
||||
public function __construct(string $phpVersion, string $fixerVersion, string $indent, string $lineEnding, array $rules)
|
||||
{
|
||||
$this->phpVersion = $phpVersion;
|
||||
$this->fixerVersion = $fixerVersion;
|
||||
$this->indent = $indent;
|
||||
$this->lineEnding = $lineEnding;
|
||||
$this->rules = self::makeJsonEncodable($rules);
|
||||
}
|
||||
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return $this->phpVersion;
|
||||
}
|
||||
|
||||
public function getFixerVersion(): string
|
||||
{
|
||||
return $this->fixerVersion;
|
||||
}
|
||||
|
||||
public function getIndent(): string
|
||||
{
|
||||
return $this->indent;
|
||||
}
|
||||
|
||||
public function getLineEnding(): string
|
||||
{
|
||||
return $this->lineEnding;
|
||||
}
|
||||
|
||||
public function getRules(): array
|
||||
{
|
||||
return $this->rules;
|
||||
}
|
||||
|
||||
public function equals(SignatureInterface $signature): bool
|
||||
{
|
||||
return $this->phpVersion === $signature->getPhpVersion()
|
||||
&& $this->fixerVersion === $signature->getFixerVersion()
|
||||
&& $this->indent === $signature->getIndent()
|
||||
&& $this->lineEnding === $signature->getLineEnding()
|
||||
&& $this->rules === $signature->getRules();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string, mixed>|bool> $data
|
||||
*
|
||||
* @return array<string, array<string, mixed>|bool>
|
||||
*/
|
||||
private static function makeJsonEncodable(array $data): array
|
||||
{
|
||||
array_walk_recursive($data, static function (&$item): void {
|
||||
if (\is_string($item) && !mb_detect_encoding($item, 'utf-8', true)) {
|
||||
$item = base64_encode($item);
|
||||
}
|
||||
});
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Cache;
|
||||
|
||||
/**
|
||||
* @author Andreas Möller <am@localheinz.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface SignatureInterface
|
||||
{
|
||||
public function getPhpVersion(): string;
|
||||
|
||||
public function getFixerVersion(): string;
|
||||
|
||||
public function getIndent(): string;
|
||||
|
||||
public function getLineEnding(): string;
|
||||
|
||||
/**
|
||||
* @return array<string, array<string, mixed>|bool>
|
||||
*/
|
||||
public function getRules(): array;
|
||||
|
||||
public function equals(self $signature): bool;
|
||||
}
|
||||
Reference in New Issue
Block a user