Skip to content

Commit

Permalink
wrong param defaultValue constant name - https://bugs.php.net/bug.php…
Browse files Browse the repository at this point in the history
…?id=73632

improve markupIdentifier / parseIdentifier
  • Loading branch information
bkdotcom committed Jul 29, 2024
1 parent b0e4846 commit 90ca6ac
Show file tree
Hide file tree
Showing 21 changed files with 258 additions and 85 deletions.
32 changes: 25 additions & 7 deletions src/Debug/Abstraction/Object/MethodParams.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,8 @@ private function getParamDefaultVal(ReflectionParameter $refParameter)
if ($defaultValue instanceof UnitEnum) {
$defaultValue = $this->abstracter->crate($defaultValue, $this->abs['debugMethod']);
} elseif (PHP_VERSION_ID >= 50406 && $refParameter->isDefaultValueConstant()) {
/*
getDefaultValueConstantName() :
php may return something like self::CONSTANT_NAME
hhvm will return WhateverTheClassNameIs::CONSTANT_NAME
*/
$defaultValue = new Abstraction(Type::TYPE_CONST, array(
'name' => $refParameter->getDefaultValueConstantName(),
'name' => $this->getConstantName($refParameter),
'value' => $defaultValue,
));
}
Expand All @@ -211,7 +206,30 @@ private function getParamDefaultVal(ReflectionParameter $refParameter)
}

/**
* Get param typehint
* Get param's default value constant name
*
* @param ReflectionParameter $refParameter reflectionParameter
*
* @return string
*/
private function getConstantName(ReflectionParameter $refParameter)
{
// getDefaultValueConstantName() :
// php may return something like self::CONSTANT_NAME
$name = $refParameter->getDefaultValueConstantName();
if (\preg_match('/^(?!.*::).*\\\\.*$/u', $name) && \defined($name) === false) {
// constant name includes "\", but does not include "::" and is not defined
// @see https://bugs.php.net/bug.php?id=73632
$index = \strrpos($name, '\\');
$name = \substr($name, $index + 1);
// \bdk\Debug::log('namespace', $refParameter->getDeclaringClass()->getNamespaceName());
// \bdk\Debug::log('namespace', $refParameter->getDeclaringFunction()->getNamespaceName());
}
return $name;
}

/**
* Get param type-hint
*
* @param ReflectionParameter $refParameter reflectionParameter
* @param string|null $phpDocType param's phpdoc type
Expand Down
30 changes: 14 additions & 16 deletions src/Debug/Dump/AbstractValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -371,39 +371,37 @@ protected function getPerValueOptions($val, $opts)
}

/**
* Split identifier into classname, operator, & identifier
* Identifier = classname, function, or property
* Split identifier into classname, operator, & identifier.
*
* @param Abstraction|array|string $val classname or classname(::|->)name (method/property/const)
* @param bool $asFunction (false)
* classname may be namespace\classname
* identifier = classname, constant function, or property
*
* @param Abstraction|array|string $val classname or classname(::|->)name (method/property/const)
* @param string $what ("classname"), "const", or "function"
*
* @return array
*/
protected function parseIdentifier($val, $asFunction = false)
protected function parseIdentifier($val, $what = 'classname')
{
if ($val instanceof Abstraction) {
$val = $val['value'];
}
$parts = array(
'classname' => $val,
'identifier' => '',
'operator' => '::',
);
$parts = \array_fill_keys(array('classname', 'identifier', 'namespace', 'operator'), '');
$parts['classname'] = $val;
$matches = array();
if (\is_array($val)) {
$parts['classname'] = $val[0];
$parts['operator'] = '::';
$parts['identifier'] = $val[1];
} elseif (\preg_match('/^(.+)(::|->)(.+)$/', $val, $matches)) {
$parts['classname'] = $matches[1];
$parts['operator'] = $matches[2];
$parts['identifier'] = $matches[3];
} elseif (\preg_match('/^(.+)(\\\\\{closure\})$/', $val, $matches)) {
$parts['classname'] = $matches[1];
$parts['operator'] = '';
$parts['identifier'] = $matches[2];
} elseif ($asFunction) {
} elseif (\in_array($what, array('const', 'function'), true)) {
\preg_match('/^(.+\\\\)?(.+)$/', $val, $matches);
$parts['classname'] = '';
$parts['identifier'] = $val;
$parts['namespace'] = $matches[1];
$parts['identifier'] = $matches[2];
}
return $parts;
}
Expand Down
6 changes: 3 additions & 3 deletions src/Debug/Dump/Base/Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ public function markupIdentifier($val)
{
if ($val instanceof Abstraction) {
$val = $val['value'];
if (\is_array($val)) {
$val = $val[0] . '::' . $val[1];
}
}
if (\is_array($val)) {
$val = $val[0] . '::' . $val[1];
}
return $this->highlightChars($val);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/Dump/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public function substitutionAsString($val, $opts)
$opts['tagName'] = null;
$toStr = (string) $val; // objects __toString or its classname
return $toStr === $val['className']
? $this->valDumper->markupIdentifier($toStr)
? $this->valDumper->markupIdentifier($toStr, 'classname')
: $this->valDumper->dump($toStr, $opts);
}
return $this->valDumper->dump($val);
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/Dump/Html/AbstractObjectSection.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ private function dumpItemsByInheritance(ObjectAbstraction $abs, array $cfg)
$items = \array_diff_key($items, $itemsFiltered);
$itemOutCount += \count($itemsFiltered);
$html .= \in_array($classNameCur, array($className, 'stdClass'), true) === false
? '<dd class="heading">Inherited from ' . $this->valDumper->markupIdentifier($classNameCur) . '</dd>' . "\n"
? '<dd class="heading">Inherited from ' . $this->valDumper->markupIdentifier($classNameCur, 'classname') . '</dd>' . "\n"
: '';
$html .= $this->dumpItemsFiltered($abs, $keys, $cfg);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/Dump/Html/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private function header(array $args, array $meta)
{
$label = \array_shift($args);
$label = $meta['isFuncName']
? $this->dumper->valDumper->markupIdentifier($label, true)
? $this->dumper->valDumper->markupIdentifier($label, 'function')
: \preg_replace('#^<span class="t_string">(.+)</span>$#s', '$1', $this->dumper->valDumper->dump($label));

$labelClasses = \implode(' ', \array_keys(\array_filter(array(
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/Dump/Html/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public function tableAddContextRow($html, array $row, array $rowInfo, $index)
public function tableMarkupFunction($html, array $row)
{
if (isset($row['function'])) {
$replace = $this->dumper->valDumper->markupIdentifier($row['function'], true, 'span', array(), true);
$replace = $this->dumper->valDumper->markupIdentifier($row['function'], 'function', 'span', array(), true);
$replace = '<td class="col-function no-quotes t_string">' . $replace . '</td>';
$html = \str_replace(
'<td class="t_string">' . \htmlspecialchars($row['function']) . '</td>',
Expand Down
8 changes: 4 additions & 4 deletions src/Debug/Dump/Html/HtmlObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ private function buildImplementsTree(array $implements, array $interfacesCollaps
'toggle-off' => \in_array($classname, $interfacesCollapse, true),
),
),
$this->valDumper->markupIdentifier($classname)
$this->valDumper->markupIdentifier($classname, 'classname')
)
. (\is_array($v) ? "\n" . self::buildImplementsTree($v, $interfacesCollapse) : '')
. '</li>' . "\n";
Expand Down Expand Up @@ -212,7 +212,7 @@ protected function dumpAttributes(ObjectAbstraction $abs)
$attributes = $abs->sort($attributes, $abs['sort']);
foreach ($attributes as $info) {
$str .= '<dd class="attribute">'
. $this->valDumper->markupIdentifier($info['name'])
. $this->valDumper->markupIdentifier($info['name'], 'classname')
. $this->dumpAttributeArgs($info['arguments'])
. '</dd>' . "\n";
}
Expand Down Expand Up @@ -273,7 +273,7 @@ protected function dumpClassname(ObjectAbstraction $abs)
$this->valDumper->markupIdentifier($abs['className'] . '::' . $abs['properties']['name']['value'])
);
}
return $this->valDumper->markupIdentifier($abs['className'], false, 'span', array(
return $this->valDumper->markupIdentifier($abs['className'], 'classname', 'span', array(
'title' => $title,
));
}
Expand All @@ -289,7 +289,7 @@ protected function dumpExtends(ObjectAbstraction $abs)
{
return '<dt>extends</dt>' . "\n"
. \implode(\array_map(function ($classname) {
return '<dd class="extends">' . $this->valDumper->markupIdentifier($classname) . '</dd>' . "\n";
return '<dd class="extends">' . $this->valDumper->markupIdentifier($classname, 'classname') . '</dd>' . "\n";
}, $abs['extends']));
}

Expand Down
2 changes: 1 addition & 1 deletion src/Debug/Dump/Html/HtmlString.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ private function buildPrettifiedPostDump(Abstraction $abs)
*/
private function dumpClassname(Abstraction $abs)
{
$val = $this->valDumper->markupIdentifier($abs['value']);
$val = $this->valDumper->markupIdentifier($abs['value'], 'classname');
$parsed = $this->debug->html->parseTag($val);
$attribs = $this->valDumper->optionGet('attribs');
$attribs = $this->debug->arrayUtil->mergeDeep($attribs, $parsed['attribs']);
Expand Down
6 changes: 3 additions & 3 deletions src/Debug/Dump/Html/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private function buildCaption()
}
$class = $this->dumper->valDumper->markupIdentifier(
$this->options['tableInfo']['class'],
false,
'classname',
'span',
array(
'title' => $this->options['tableInfo']['summary'] ?: null,
Expand Down Expand Up @@ -171,7 +171,7 @@ protected function buildHeader()
foreach ($this->options['tableInfo']['columns'] as $colInfo) {
$label = $colInfo['key'];
if (isset($colInfo['class'])) {
$label .= ' ' . $this->dumper->valDumper->markupIdentifier($colInfo['class']);
$label .= ' ' . $this->dumper->valDumper->markupIdentifier($colInfo['class'], 'classname');
}
$labels[] = $label;
}
Expand Down Expand Up @@ -219,7 +219,7 @@ protected function buildRow($row, array $rowInfo, $rowKey)
*/
if ($this->options['tableInfo']['haveObjRow']) {
$str .= $rowInfo['class']
? $this->dumper->valDumper->markupIdentifier($rowInfo['class'], false, 'td', array(
? $this->dumper->valDumper->markupIdentifier($rowInfo['class'], 'classname', 'td', array(
'title' => $rowInfo['summary'] ?: null,
))
: '<td class="t_undefined"></td>';
Expand Down
54 changes: 29 additions & 25 deletions src/Debug/Dump/Html/Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,35 +119,39 @@ public function dump($val, $opts = array())
* if namespaced additionally wrap namespace in span.namespace
* If callable, also wrap with .t_operator and .t_identifier
*
* @param mixed $val classname or classname(::|->)name (method/property/const)
* @param string $asFunction (false) specify we're marking up a function
* @param string $tagName ("span") html tag to use
* @param array $attribs (optional) additional html attributes for classname span
* @param bool $wbr (false) whether to add a <wbr /> after the classname
* @param mixed $val classname or classname(::|->)name (method/property/const)
* @param string $what ("classname"), "const", or "function" - specify what we're marking if ambiguous
* @param string $tagName ("span") html tag to use
* @param array $attribs (optional) additional html attributes for classname span (such as title)
* @param bool $wbr (false) whether to add a <wbr /> after the classname
*
* @return string html snippet
*/
public function markupIdentifier($val, $asFunction = false, $tagName = 'span', $attribs = array(), $wbr = false)
public function markupIdentifier($val, $what = 'classname', $tagName = 'span', $attribs = array(), $wbr = false)
{
$parts = \array_map(array($this->string, 'dump'), $this->parseIdentifier($val, $asFunction));
$operator = '<span class="t_operator">' . $parts['operator'] . '</span>';
if ($parts['classname']) {
$parts['classname'] = $this->debug->html->buildTag(
$tagName,
$this->debug->arrayUtil->mergeDeep(array(
'class' => array('classname'),
), (array) $attribs),
$this->wrapNamespace($parts['classname'])
) . '<wbr />';
$parts = \array_map(array($this->string, 'dump'), $this->parseIdentifier($val, $what));
$class = 'classname';
$classOrNamespace = $this->wrapNamespace($parts['classname']);
if ($parts['namespace']) {
$class = 'namespace';
$classOrNamespace = $parts['namespace'];
}
if ($parts['identifier']) {
$parts['identifier'] = '<span class="t_identifier">' . $this->wrapNamespace($parts['identifier']) . '</span>';
$classOrNamespace = $this->html->buildTag(
$tagName,
$this->debug->arrayUtil->mergeDeep(array(
'class' => array($class),
), (array) $attribs),
$classOrNamespace
) . '<wbr />';
$classOrNamespace = \preg_replace('#<' . $tagName . '[^>]*></' . $tagName . '><wbr />#', '', $classOrNamespace);
$parts2 = \array_filter(\array_intersect_key($parts, \array_flip(array('operator', 'identifier'))));
foreach ($parts2 as $key => $value) {
$parts[$key] = '<span class="t_' . $key . '">' . $value . '</span>';
}
$html = \implode($operator, \array_filter(array($parts['classname'], $parts['identifier']), 'strlen'));
if ($wbr === false) {
$html = \str_replace('<wbr />', '', $html);
}
return $html;
$html = \implode($parts['operator'], \array_filter(array($classOrNamespace, $parts['identifier'])));
return $wbr === false
? \str_replace('<wbr />', '', $html)
: $html;
}

/**
Expand Down Expand Up @@ -271,10 +275,10 @@ protected function dumpCallable(Abstraction $abs)
*/
protected function dumpConst(Abstraction $abs)
{
$this->optionSet('attribs.title', $abs['value']
$this->optionSet('attribs.title', isset($abs['value'])
? 'value: ' . $this->debug->getDump('text')->valDumper->dump($abs['value'])
: null);
return $this->markupIdentifier($abs['name']);
return $this->markupIdentifier($abs['name'], 'const');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/Dump/Text.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ private function methodGroupBuildOutput(LogEntry $logEntry)
), $logEntry['meta']);
$label = \array_shift($args);
$label = $meta['isFuncName']
? $this->valDumper->markupIdentifier($label, true)
? $this->valDumper->markupIdentifier($label, 'function')
: $this->valDumper->dump($label, array('addQuotes' => false));
foreach ($args as $k => $v) {
$args[$k] = $this->valDumper->dump($v);
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/Dump/Text/TextObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function __construct(ValDumper $valDumper)
*/
public function dump(ObjectAbstraction $abs)
{
$className = $this->valDumper->markupIdentifier($abs['className']);
$className = $this->valDumper->markupIdentifier($abs['className'], 'classname');
if ($abs['isRecursion']) {
return $className . ' *RECURSION*';
}
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/Dump/TextAnsi/TextAnsiObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function __construct(ValDumper $valDumper)
*/
public function dump(ObjectAbstraction $abs)
{
$className = $this->valDumper->markupIdentifier($abs['className']);
$className = $this->valDumper->markupIdentifier($abs['className'], 'classname');
$escapeCodes = $this->valDumper->getCfg('escapeCodes');
$escapeReset = $this->valDumper->escapeReset;
if ($abs['isRecursion']) {
Expand Down
Loading

0 comments on commit 90ca6ac

Please sign in to comment.