mirror of https://github.com/rectorphp/rector.git
238 lines
6.7 KiB
PHP
238 lines
6.7 KiB
PHP
<?php
|
|
|
|
declare (strict_types=1);
|
|
namespace Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation;
|
|
|
|
use RectorPrefix20210808\Nette\Utils\Strings;
|
|
use PHPStan\PhpDocParser\Ast\Node;
|
|
use PHPStan\PhpDocParser\Ast\NodeAttributes;
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
|
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
|
|
abstract class AbstractValuesAwareNode implements \PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode
|
|
{
|
|
use NodeAttributes;
|
|
/**
|
|
* @var string
|
|
* @see https://regex101.com/r/H6JjOG/3
|
|
*/
|
|
private const UNQUOTED_VALUE_REGEX = '#^("|\')(?<content>.*?)("|\')$#';
|
|
/**
|
|
* @var bool
|
|
*/
|
|
protected $hasChanged = \false;
|
|
/**
|
|
* @var mixed[]
|
|
*/
|
|
private $originalValues = [];
|
|
/**
|
|
* @var mixed[]
|
|
*/
|
|
public $values = [];
|
|
/**
|
|
* @var string|null
|
|
*/
|
|
protected $originalContent;
|
|
/**
|
|
* @var string|null
|
|
*/
|
|
protected $silentKey;
|
|
/**
|
|
* @param mixed[] $values Must be public so node traverser can go through them
|
|
*/
|
|
public function __construct(array $values = [], ?string $originalContent = null, ?string $silentKey = null)
|
|
{
|
|
$this->values = $values;
|
|
$this->originalContent = $originalContent;
|
|
$this->silentKey = $silentKey;
|
|
$this->originalValues = $values;
|
|
}
|
|
public function removeValue(string $key) : void
|
|
{
|
|
$quotedKey = '"' . $key . '"';
|
|
// isset?
|
|
if (!isset($this->values[$key]) && !isset($this->values[$quotedKey])) {
|
|
return;
|
|
}
|
|
unset($this->values[$key]);
|
|
unset($this->values[$quotedKey]);
|
|
// invoke reprint
|
|
$this->setAttribute(\Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey::ORIG_NODE, null);
|
|
}
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
public function getValues() : array
|
|
{
|
|
return $this->values;
|
|
}
|
|
/**
|
|
* @return mixed|Node|null
|
|
* @param string|int $key
|
|
*/
|
|
public function getValue($key)
|
|
{
|
|
// to allow false as default
|
|
if (!\array_key_exists($key, $this->values)) {
|
|
return null;
|
|
}
|
|
return $this->values[$key];
|
|
}
|
|
/**
|
|
* @param mixed $value
|
|
*/
|
|
public function changeValue(string $key, $value) : void
|
|
{
|
|
// is quoted?
|
|
if (isset($this->values[$key])) {
|
|
$isQuoted = (bool) \RectorPrefix20210808\Nette\Utils\Strings::match($this->values[$key], self::UNQUOTED_VALUE_REGEX);
|
|
if ($isQuoted) {
|
|
$value = '"' . $value . '"';
|
|
}
|
|
}
|
|
$this->values[$key] = $value;
|
|
// invoke reprint
|
|
$this->setAttribute(\Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey::ORIG_NODE, null);
|
|
}
|
|
/**
|
|
* @return mixed|null
|
|
* @param string|int $key
|
|
*/
|
|
public function getValueWithoutQuotes($key)
|
|
{
|
|
$value = $this->getValue($key);
|
|
if ($value === null) {
|
|
return null;
|
|
}
|
|
return $this->removeQuotes($value);
|
|
}
|
|
/**
|
|
* @param mixed $value
|
|
*/
|
|
public function changeSilentValue($value) : void
|
|
{
|
|
// is quoted?
|
|
$isQuoted = (bool) \RectorPrefix20210808\Nette\Utils\Strings::match($this->values[0], self::UNQUOTED_VALUE_REGEX);
|
|
if ($isQuoted) {
|
|
$value = '"' . $value . '"';
|
|
}
|
|
$this->values[0] = $value;
|
|
$this->hasChanged = \true;
|
|
// invoke reprint
|
|
$this->setAttribute(\Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey::ORIG_NODE, null);
|
|
}
|
|
/**
|
|
* @return mixed|null
|
|
*/
|
|
public function getSilentValue()
|
|
{
|
|
$value = $this->values[0] ?? null;
|
|
if ($value === null) {
|
|
return null;
|
|
}
|
|
return $this->removeQuotes($value);
|
|
}
|
|
/**
|
|
* Useful for attributes
|
|
* @return array<int|string, mixed>
|
|
*/
|
|
public function getValuesWithExplicitSilentAndWithoutQuotes() : array
|
|
{
|
|
$explicitKeysValues = [];
|
|
foreach (\array_keys($this->values) as $key) {
|
|
$valueWithoutQuotes = $this->getValueWithoutQuotes($key);
|
|
if (\is_int($key) && $this->silentKey !== null) {
|
|
$explicitKeysValues[$this->silentKey] = $valueWithoutQuotes;
|
|
} else {
|
|
$explicitKeysValues[$this->removeQuotes($key)] = $valueWithoutQuotes;
|
|
}
|
|
}
|
|
return $explicitKeysValues;
|
|
}
|
|
public function markAsChanged() : void
|
|
{
|
|
$this->hasChanged = \true;
|
|
}
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
public function getOriginalValues() : array
|
|
{
|
|
return $this->originalValues;
|
|
}
|
|
/**
|
|
* @param mixed|string $value
|
|
* @return mixed|string
|
|
*/
|
|
protected function removeQuotes($value)
|
|
{
|
|
if (\is_array($value)) {
|
|
return $this->removeQuotesFromArray($value);
|
|
}
|
|
if (!\is_string($value)) {
|
|
return $value;
|
|
}
|
|
$matches = \RectorPrefix20210808\Nette\Utils\Strings::match($value, self::UNQUOTED_VALUE_REGEX);
|
|
if ($matches === null) {
|
|
return $value;
|
|
}
|
|
return $matches['content'];
|
|
}
|
|
/**
|
|
* @param mixed[] $values
|
|
* @return array<int|string, mixed>
|
|
*/
|
|
protected function removeQuotesFromArray(array $values) : array
|
|
{
|
|
$unquotedArray = [];
|
|
foreach ($values as $key => $value) {
|
|
$unquotedKey = $this->removeQuotes($key);
|
|
$unquotedValue = $this->removeQuotes($value);
|
|
$unquotedArray[$unquotedKey] = $unquotedValue;
|
|
}
|
|
return $unquotedArray;
|
|
}
|
|
/**
|
|
* @param mixed[] $values
|
|
*/
|
|
protected function printValuesContent(array $values) : string
|
|
{
|
|
$itemContents = '';
|
|
\end($values);
|
|
$lastItemKey = \key($values);
|
|
foreach ($values as $key => $value) {
|
|
if (\is_int($key)) {
|
|
$itemContents .= $this->stringifyValue($value);
|
|
} else {
|
|
$itemContents .= $key . '=' . $this->stringifyValue($value);
|
|
}
|
|
if ($lastItemKey !== $key) {
|
|
$itemContents .= ', ';
|
|
}
|
|
}
|
|
return $itemContents;
|
|
}
|
|
/**
|
|
* @param mixed $value
|
|
*/
|
|
private function stringifyValue($value) : string
|
|
{
|
|
// @todo resolve original casing
|
|
if ($value === \false) {
|
|
return 'false';
|
|
}
|
|
if ($value === \true) {
|
|
return 'true';
|
|
}
|
|
if (\is_int($value)) {
|
|
return (string) $value;
|
|
}
|
|
if (\is_float($value)) {
|
|
return (string) $value;
|
|
}
|
|
if (\is_array($value)) {
|
|
return $this->printValuesContent($value);
|
|
}
|
|
return (string) $value;
|
|
}
|
|
}
|