mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-19 15:22:17 +02:00
N°8834 - Add compatibility with PHP 8.4 (#819)
* N°8834 - Add compatibility with PHP 8.4 * Rollback of scssphp/scssphp version upgrade due to compilation error
This commit is contained in:
@@ -47,7 +47,7 @@ class Caster
|
||||
*
|
||||
* @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not
|
||||
*/
|
||||
public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, string $debugClass = null): array
|
||||
public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, ?string $debugClass = null): array
|
||||
{
|
||||
if ($hasDebugInfo) {
|
||||
try {
|
||||
|
||||
@@ -24,7 +24,7 @@ class ClassStub extends ConstStub
|
||||
* @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name
|
||||
* @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier
|
||||
*/
|
||||
public function __construct(string $identifier, callable|array|string $callable = null)
|
||||
public function __construct(string $identifier, callable|array|string|null $callable = null)
|
||||
{
|
||||
$this->value = $identifier;
|
||||
|
||||
@@ -56,7 +56,7 @@ class ClassStub extends ConstStub
|
||||
}
|
||||
|
||||
if (str_contains($identifier, "@anonymous\0")) {
|
||||
$this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $identifier);
|
||||
$this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $identifier);
|
||||
}
|
||||
|
||||
if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) {
|
||||
|
||||
@@ -20,7 +20,7 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
*/
|
||||
class ConstStub extends Stub
|
||||
{
|
||||
public function __construct(string $name, string|int|float $value = null)
|
||||
public function __construct(string $name, string|int|float|null $value = null)
|
||||
{
|
||||
$this->class = $name;
|
||||
$this->value = 1 < \func_num_args() ? $value : $name;
|
||||
|
||||
@@ -27,7 +27,7 @@ class CutStub extends Stub
|
||||
switch (\gettype($value)) {
|
||||
case 'object':
|
||||
$this->type = self::TYPE_OBJECT;
|
||||
$this->class = $value::class;
|
||||
$this->class = get_debug_type($value);
|
||||
|
||||
if ($value instanceof \Closure) {
|
||||
ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE);
|
||||
|
||||
@@ -23,7 +23,7 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
class DOMCaster
|
||||
{
|
||||
private const ERROR_CODES = [
|
||||
\DOM_PHP_ERR => 'DOM_PHP_ERR',
|
||||
0 => 'DOM_PHP_ERR',
|
||||
\DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR',
|
||||
\DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR',
|
||||
\DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR',
|
||||
@@ -156,16 +156,12 @@ class DOMCaster
|
||||
'doctype' => $dom->doctype,
|
||||
'implementation' => $dom->implementation,
|
||||
'documentElement' => new CutStub($dom->documentElement),
|
||||
'actualEncoding' => $dom->actualEncoding,
|
||||
'encoding' => $dom->encoding,
|
||||
'xmlEncoding' => $dom->xmlEncoding,
|
||||
'standalone' => $dom->standalone,
|
||||
'xmlStandalone' => $dom->xmlStandalone,
|
||||
'version' => $dom->version,
|
||||
'xmlVersion' => $dom->xmlVersion,
|
||||
'strictErrorChecking' => $dom->strictErrorChecking,
|
||||
'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI,
|
||||
'config' => $dom->config,
|
||||
'formatOutput' => $dom->formatOutput,
|
||||
'validateOnParse' => $dom->validateOnParse,
|
||||
'resolveExternals' => $dom->resolveExternals,
|
||||
@@ -277,9 +273,6 @@ class DOMCaster
|
||||
'publicId' => $dom->publicId,
|
||||
'systemId' => $dom->systemId,
|
||||
'notationName' => $dom->notationName,
|
||||
'actualEncoding' => $dom->actualEncoding,
|
||||
'encoding' => $dom->encoding,
|
||||
'version' => $dom->version,
|
||||
];
|
||||
|
||||
return $a;
|
||||
|
||||
@@ -105,16 +105,16 @@ class DateCaster
|
||||
foreach (clone $p as $i => $d) {
|
||||
if (self::PERIOD_LIMIT === $i) {
|
||||
$now = new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
|
||||
$dates[] = sprintf('%s more', ($end = $p->getEndDate())
|
||||
$dates[] = \sprintf('%s more', ($end = $p->getEndDate())
|
||||
? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u')))
|
||||
: $p->recurrences - $i
|
||||
);
|
||||
break;
|
||||
}
|
||||
$dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d));
|
||||
$dates[] = \sprintf('%s) %s', $i + 1, self::formatDateTime($d));
|
||||
}
|
||||
|
||||
$period = sprintf(
|
||||
$period = \sprintf(
|
||||
'every %s, from %s%s %s',
|
||||
self::formatInterval($p->getDateInterval()),
|
||||
$p->include_start_date ? '[' : ']',
|
||||
@@ -134,6 +134,6 @@ class DateCaster
|
||||
|
||||
private static function formatSeconds(string $s, string $us): string
|
||||
{
|
||||
return sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us));
|
||||
return \sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class ExceptionCaster
|
||||
\E_USER_ERROR => 'E_USER_ERROR',
|
||||
\E_USER_WARNING => 'E_USER_WARNING',
|
||||
\E_USER_NOTICE => 'E_USER_NOTICE',
|
||||
\E_STRICT => 'E_STRICT',
|
||||
2048 => 'E_STRICT',
|
||||
];
|
||||
|
||||
private static array $framesCache = [];
|
||||
@@ -192,7 +192,7 @@ class ExceptionCaster
|
||||
} else {
|
||||
$label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall;
|
||||
}
|
||||
$a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame;
|
||||
$a[substr_replace($label, \sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame;
|
||||
|
||||
$lastCall = $call;
|
||||
}
|
||||
@@ -240,7 +240,7 @@ class ExceptionCaster
|
||||
if (isset($f['object'])) {
|
||||
$template = $f['object'];
|
||||
} elseif ((new \ReflectionClass($f['class']))->isInstantiable()) {
|
||||
$template = unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
|
||||
$template = unserialize(\sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
|
||||
}
|
||||
if (null !== $template) {
|
||||
$ellipsis = 0;
|
||||
@@ -264,7 +264,7 @@ class ExceptionCaster
|
||||
$ellipsis += 1 + \strlen($f['line']);
|
||||
}
|
||||
}
|
||||
$srcAttr .= sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']);
|
||||
$srcAttr .= \sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']);
|
||||
} else {
|
||||
$srcAttr .= '&separator=:';
|
||||
}
|
||||
@@ -295,7 +295,7 @@ class ExceptionCaster
|
||||
public static function castFlattenException(FlattenException $e, array $a, Stub $stub, bool $isNested)
|
||||
{
|
||||
if ($isNested) {
|
||||
$k = sprintf(Caster::PATTERN_PRIVATE, FlattenException::class, 'traceAsString');
|
||||
$k = \sprintf(Caster::PATTERN_PRIVATE, FlattenException::class, 'traceAsString');
|
||||
$a[$k] = new CutStub($a[$k]);
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ class ExceptionCaster
|
||||
unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message']);
|
||||
|
||||
if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], "@anonymous\0")) {
|
||||
$a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $a[Caster::PREFIX_PROTECTED.'message']);
|
||||
$a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $a[Caster::PREFIX_PROTECTED.'message']);
|
||||
}
|
||||
|
||||
if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {
|
||||
@@ -411,7 +411,7 @@ class ExceptionCaster
|
||||
}
|
||||
}
|
||||
$c->attr['lang'] = $lang;
|
||||
$srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c;
|
||||
$srcLines[\sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c;
|
||||
}
|
||||
|
||||
return new EnumStub($srcLines);
|
||||
|
||||
@@ -41,7 +41,7 @@ final class FFICaster
|
||||
$type = \FFI::typeof($data);
|
||||
}
|
||||
|
||||
$stub->class = sprintf('%s<%s> size %d align %d', ($data ?? $type)::class, $type->getName(), $type->getSize(), $type->getAlignment());
|
||||
$stub->class = \sprintf('%s<%s> size %d align %d', ($data ?? $type)::class, $type->getName(), $type->getSize(), $type->getAlignment());
|
||||
|
||||
return match ($type->getKind()) {
|
||||
CType::TYPE_FLOAT,
|
||||
@@ -86,7 +86,7 @@ final class FFICaster
|
||||
CType::ABI_MS => '[ms]',
|
||||
CType::ABI_SYSV => '[sysv]',
|
||||
CType::ABI_VECTORCALL => '[vectorcall]',
|
||||
default => '[unknown abi]'
|
||||
default => '[unknown abi]',
|
||||
};
|
||||
|
||||
$returnType = $type->getFuncReturnType();
|
||||
@@ -97,7 +97,7 @@ final class FFICaster
|
||||
return [Caster::PREFIX_VIRTUAL.'returnType' => $returnType];
|
||||
}
|
||||
|
||||
private static function castFFIPointer(Stub $stub, CType $type, CData $data = null): array
|
||||
private static function castFFIPointer(Stub $stub, CType $type, ?CData $data = null): array
|
||||
{
|
||||
$ptr = $type->getPointerType();
|
||||
|
||||
@@ -115,11 +115,21 @@ final class FFICaster
|
||||
private static function castFFIStringValue(CData $data): string|CutStub
|
||||
{
|
||||
$result = [];
|
||||
$ffi = \FFI::cdef(<<<C
|
||||
size_t zend_get_page_size(void);
|
||||
C);
|
||||
|
||||
for ($i = 0; $i < self::MAX_STRING_LENGTH; ++$i) {
|
||||
$pageSize = $ffi->zend_get_page_size();
|
||||
|
||||
// get cdata address
|
||||
$start = $ffi->cast('uintptr_t', $ffi->cast('char*', $data))->cdata;
|
||||
// accessing memory in the same page as $start is safe
|
||||
$max = min(self::MAX_STRING_LENGTH, ($start | ($pageSize - 1)) - $start);
|
||||
|
||||
for ($i = 0; $i < $max; ++$i) {
|
||||
$result[$i] = $data[$i];
|
||||
|
||||
if ("\0" === $result[$i]) {
|
||||
if ("\0" === $data[$i]) {
|
||||
return implode('', $result);
|
||||
}
|
||||
}
|
||||
@@ -132,7 +142,7 @@ final class FFICaster
|
||||
return $stub;
|
||||
}
|
||||
|
||||
private static function castFFIStructLike(CType $type, CData $data = null): array
|
||||
private static function castFFIStructLike(CType $type, ?CData $data = null): array
|
||||
{
|
||||
$isUnion = ($type->getAttributes() & CType::ATTR_UNION) === CType::ATTR_UNION;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class LinkStub extends ConstStub
|
||||
private static array $vendorRoots;
|
||||
private static array $composerRoots = [];
|
||||
|
||||
public function __construct(string $label, int $line = 0, string $href = null)
|
||||
public function __construct(string $label, int $line = 0, ?string $href = null)
|
||||
{
|
||||
$this->value = $label;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Symfony\Component\VarDumper\Caster;
|
||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
|
||||
/**
|
||||
* Casts pqsql resources to array representation.
|
||||
* Casts pgsql resources to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
@@ -140,11 +140,11 @@ class PgSqlCaster
|
||||
for ($i = 0; $i < $fields; ++$i) {
|
||||
$field = [
|
||||
'name' => pg_field_name($result, $i),
|
||||
'table' => sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)),
|
||||
'type' => sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)),
|
||||
'nullable' => (bool) pg_field_is_null($result, $i),
|
||||
'table' => \sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)),
|
||||
'type' => \sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)),
|
||||
'nullable' => (bool) (\PHP_VERSION_ID >= 80300 ? pg_field_is_null($result, null, $i) : pg_field_is_null($result, $i)),
|
||||
'storage' => pg_field_size($result, $i).' bytes',
|
||||
'display' => pg_field_prtlen($result, $i).' chars',
|
||||
'display' => (\PHP_VERSION_ID >= 80300 ? pg_field_prtlen($result, null, $i) : pg_field_prtlen($result, $i)).' chars',
|
||||
];
|
||||
if (' (OID: )' === $field['table']) {
|
||||
$field['table'] = null;
|
||||
|
||||
@@ -45,7 +45,7 @@ class ReflectionCaster
|
||||
|
||||
$a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter);
|
||||
|
||||
if (!str_contains($c->name, '{closure}')) {
|
||||
if (!str_contains($c->name, '{closure')) {
|
||||
$stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name;
|
||||
unset($a[$prefix.'class']);
|
||||
}
|
||||
@@ -89,13 +89,13 @@ class ReflectionCaster
|
||||
// Cannot create ReflectionGenerator based on a terminated Generator
|
||||
try {
|
||||
$reflectionGenerator = new \ReflectionGenerator($c);
|
||||
|
||||
return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested);
|
||||
} catch (\Exception) {
|
||||
$a[Caster::PREFIX_VIRTUAL.'closed'] = true;
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,10 +128,16 @@ class ReflectionCaster
|
||||
*/
|
||||
public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested)
|
||||
{
|
||||
self::addMap($a, $c, [
|
||||
$map = [
|
||||
'name' => 'getName',
|
||||
'arguments' => 'getArguments',
|
||||
]);
|
||||
];
|
||||
|
||||
if (\PHP_VERSION_ID >= 80400) {
|
||||
unset($map['name']);
|
||||
}
|
||||
|
||||
self::addMap($a, $c, $map);
|
||||
|
||||
return $a;
|
||||
}
|
||||
@@ -225,7 +231,7 @@ class ReflectionCaster
|
||||
if (isset($a[$prefix.'returnType'])) {
|
||||
$v = $a[$prefix.'returnType'];
|
||||
$v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
|
||||
$a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);
|
||||
$a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && !\in_array($v, ['mixed', 'null'], true) ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);
|
||||
}
|
||||
if (isset($a[$prefix.'class'])) {
|
||||
$a[$prefix.'class'] = new ClassStub($a[$prefix.'class']);
|
||||
@@ -407,7 +413,7 @@ class ReflectionCaster
|
||||
if (!$type instanceof \ReflectionNamedType) {
|
||||
$signature .= $type.' ';
|
||||
} else {
|
||||
if (!$param->isOptional() && $param->allowsNull() && 'mixed' !== $type->getName()) {
|
||||
if ($param->allowsNull() && !\in_array($type->getName(), ['mixed', 'null'], true)) {
|
||||
$signature .= '?';
|
||||
}
|
||||
$signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' ';
|
||||
|
||||
@@ -141,7 +141,7 @@ class SplCaster
|
||||
}
|
||||
|
||||
if (isset($a[$prefix.'perms'])) {
|
||||
$a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);
|
||||
$a[$prefix.'perms'] = new ConstStub(\sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);
|
||||
}
|
||||
|
||||
static $mapDate = ['aTime', 'mTime', 'cTime'];
|
||||
@@ -208,7 +208,7 @@ class SplCaster
|
||||
$storage[] = new EnumStub([
|
||||
'object' => $obj,
|
||||
'info' => $clone->getInfo(),
|
||||
]);
|
||||
]);
|
||||
}
|
||||
|
||||
$a += [
|
||||
@@ -249,7 +249,7 @@ class SplCaster
|
||||
$map[] = new EnumStub([
|
||||
'object' => $obj,
|
||||
'data' => $data,
|
||||
]);
|
||||
]);
|
||||
}
|
||||
|
||||
$a += [
|
||||
|
||||
@@ -54,7 +54,7 @@ class SymfonyCaster
|
||||
*/
|
||||
public static function castHttpClient($client, array $a, Stub $stub, bool $isNested)
|
||||
{
|
||||
$multiKey = sprintf("\0%s\0multi", $client::class);
|
||||
$multiKey = \sprintf("\0%s\0multi", $client::class);
|
||||
if (isset($a[$multiKey])) {
|
||||
$a[$multiKey] = new CutStub($a[$multiKey]);
|
||||
}
|
||||
@@ -90,12 +90,14 @@ class SymfonyCaster
|
||||
|
||||
$instance = $a['realInstance'] ?? null;
|
||||
|
||||
$a = ['status' => new ConstStub(match ($a['status']) {
|
||||
LazyObjectState::STATUS_INITIALIZED_FULL => 'INITIALIZED_FULL',
|
||||
LazyObjectState::STATUS_INITIALIZED_PARTIAL => 'INITIALIZED_PARTIAL',
|
||||
LazyObjectState::STATUS_UNINITIALIZED_FULL => 'UNINITIALIZED_FULL',
|
||||
LazyObjectState::STATUS_UNINITIALIZED_PARTIAL => 'UNINITIALIZED_PARTIAL',
|
||||
}, $a['status'])];
|
||||
if (isset($a['status'])) { // forward-compat with Symfony 8
|
||||
$a = ['status' => new ConstStub(match ($a['status']) {
|
||||
LazyObjectState::STATUS_INITIALIZED_FULL => 'INITIALIZED_FULL',
|
||||
LazyObjectState::STATUS_INITIALIZED_PARTIAL => 'INITIALIZED_PARTIAL',
|
||||
LazyObjectState::STATUS_UNINITIALIZED_FULL => 'UNINITIALIZED_FULL',
|
||||
LazyObjectState::STATUS_UNINITIALIZED_PARTIAL => 'UNINITIALIZED_PARTIAL',
|
||||
}, $a['status'])];
|
||||
}
|
||||
|
||||
if ($instance) {
|
||||
$a['realInstance'] = $instance;
|
||||
|
||||
@@ -25,7 +25,7 @@ class TraceStub extends Stub
|
||||
public $sliceLength;
|
||||
public $numberingOffset;
|
||||
|
||||
public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, int $sliceLength = null, int $numberingOffset = 0)
|
||||
public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, ?int $sliceLength = null, int $numberingOffset = 0)
|
||||
{
|
||||
$this->value = $trace;
|
||||
$this->keepArgs = $keepArgs;
|
||||
|
||||
Reference in New Issue
Block a user