Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
32bdc58
Add new Table utility.. represent a table / build a table from data
bkdotcom Dec 29, 2025
f36f54c
markupIdentifier & parseIdentifier - utilize the Type::TYPE_IDENTIFIE…
bkdotcom Dec 29, 2025
4fed522
add missing array typehints
bkdotcom Jan 10, 2026
b6a0faa
Updates to \bdk\Table
bkdotcom Jan 12, 2026
62be99f
Table refactor (WIP)
bkdotcom Jan 22, 2026
385f7b3
Zest.extend() not removing duplicate values after merging two arrays
bkdotcom Jan 26, 2026
e02d921
WampCrate - recurse Type::TYPE_TABLE
bkdotcom Jan 30, 2026
926ed54
Zest: typeof object / null bug
bkdotcom Jan 30, 2026
986a9e7
update MysqliTest
bkdotcom Jan 30, 2026
e34cb66
cleanup / coding standards
bkdotcom Feb 2, 2026
37df69c
coding standards
bkdotcom Feb 3, 2026
5f4f2f1
SoapClient CompatTrait
bkdotcom Feb 3, 2026
145bac7
Merge branch 'master' into Table
bkdotcom Feb 3, 2026
a4aafa2
Move Table Abstraction to Object\Subscriber
bkdotcom Feb 7, 2026
d9df6bd
New Table/Factory option: inclIndex (true)
bkdotcom Feb 8, 2026
743e6bc
update unit test
bkdotcom Feb 8, 2026
10ebcfd
Update unit tests
bkdotcom Feb 8, 2026
85234d6
Unit test fix
bkdotcom Feb 9, 2026
540cf62
DoctrineMiddleware params class issue
bkdotcom Feb 9, 2026
916d8ed
Troubleshoot DoctrineMiddlewareTest issues
bkdotcom Feb 9, 2026
40a9dc1
Update Method/TableTest (Closure signature changes not important)
bkdotcom Feb 9, 2026
1c64a06
TableCell::objectToString - remove object typehint
bkdotcom Feb 9, 2026
99a9bc0
Table tests - remove anonymous classes
bkdotcom Feb 9, 2026
7707e58
Table tests - use AssertionTrait
bkdotcom Feb 9, 2026
bdbe7a5
Table/FactoryTest - use AssertionTrait
bkdotcom Feb 9, 2026
cd7c08d
tweak ChromeLoggerTest
bkdotcom Feb 9, 2026
c265aa7
remove use of null coalescing operator
bkdotcom Feb 9, 2026
5449e1f
TableCellTest - remove DateTimeImmutable test
bkdotcom Feb 9, 2026
2035d6c
Troubleshoot unit tests
bkdotcom Feb 9, 2026
b7f02cd
update Table/ElementTest
bkdotcom Feb 10, 2026
cfd8127
phpunit - add --testdox-summary flat
bkdotcom Feb 10, 2026
bba9a94
remove --testdox-summary flag
bkdotcom Feb 10, 2026
873adca
use ExpectExceptionTrait
bkdotcom Feb 10, 2026
8340f6b
Merge branch '3.6' into Table
bkdotcom Feb 10, 2026
fe80625
implement a couple code-review suggestions
bkdotcom Feb 10, 2026
3a1bd94
Don't needlessly serialize unused classDefinitions (ie Table, TableR…
bkdotcom Feb 12, 2026
dfa2bb8
LogRequest & LogResponse no longer create channel if not logging
bkdotcom Feb 18, 2026
f4e7c62
Update SerializationLogTest
bkdotcom Feb 18, 2026
e3fd3b6
Update comments
bkdotcom Feb 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
<testsuite name="Slack">
<directory>tests/Slack</directory>
</testsuite>
<testsuite name="Table">
<directory>tests/Table</directory>
</testsuite>
<testsuite name="Teams">
<directory>tests/Teams</directory>
</testsuite>
Expand Down
2 changes: 1 addition & 1 deletion src/Backtrace/Backtrace.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public static function getCallerInfo($offset = 0, $options = 0)
we need to collect object... we'll remove object at end if undesired
*/
$phpOptions = static::translateOptions($options | self::INCL_OBJECT);
$backtrace = \debug_backtrace($phpOptions, 33);
$backtrace = \debug_backtrace($phpOptions, 60);
$backtrace = self::normalize($backtrace);
$index = SkipInternal::getFirstIndex($backtrace, $offset);
$index = \max($index, 1); // ensure we're >= 1
Expand Down
12 changes: 7 additions & 5 deletions src/Container/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* Forked from pimple/pimple
* adds:
* get()
* getObject()
* has()
* needsInvoked()
* setCfg()
Expand Down Expand Up @@ -97,7 +98,7 @@ class Container implements ArrayAccess
* @param array $values The parameters or objects
* @param array $cfg Config options
*/
public function __construct($values = array(), $cfg = array())
public function __construct(array $values = array(), array $cfg = array())
{
$this->factories = new SplObjectStorage();
$this->protected = new SplObjectStorage();
Expand Down Expand Up @@ -213,16 +214,17 @@ public function get($name)
*
* Attempt to resolve any constructor arguments from the container.
*
* @param string $classname Classname of the object to instantiate
* @param string $classname Classname of the object to instantiate
* @param bool $useContainer (true) Pull from container if available / store obj in container after build. False is similar to factory behavior.
*
* @return object
*/
public function getObject($classname)
public function getObject($classname, $useContainer = true)
{
if ($this->objectBuilder === null) {
$this->objectBuilder = new ObjectBuilder($this);
}
return $this->objectBuilder->build($classname);
return $this->objectBuilder->build($classname, $useContainer);
}

/**
Expand Down Expand Up @@ -457,7 +459,7 @@ public function setCfg($mixed, $value = null)
*
* @return $this
*/
public function setValues($values)
public function setValues(array $values)
{
foreach ($values as $key => $value) {
$this->offsetSet($key, $value);
Expand Down
38 changes: 12 additions & 26 deletions src/Container/ObjectBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,7 @@
use RuntimeException;

/**
* Container
*
* Forked from pimple/pimple
* adds:
* get()
* has()
* needsInvoked()
* setCfg()
* allowOverride & onInvoke callback
* setValues()
*
* @author Fabien Potencier
* @author Brad Kent <bkfake-github@yahoo.com>
* Instantiate objects with dependencies resolved via the container
*/
class ObjectBuilder
{
Expand Down Expand Up @@ -82,33 +70,31 @@ public function __construct(Container $container)
*
* We will look for the class in the container
* If it is not found, we will try to instantiate it via reflection and obtaining dependencies via the container
* We will save the instance in the container
*
* @param string $classname Fully qualified class name
* @param bool $addToContainer (true) Add instantiated object to container?
* if $save is true, we will save the instance in the container
*
* @param string $classname Fully qualified class name
* @param bool $save (true) store built object in container after build
*
* @return object
*
* @throws RuntimeException
*/
public function build($classname, $addToContainer = true)
public function build($classname, $save = true)
{
if ($this->container->has($classname)) {
return $this->container->get($classname);
}
$refClass = new ReflectionClass($classname);
$refConstructor = $refClass->getConstructor();
if ($refConstructor === null) {
$return = new $classname();
$paramValues = $refConstructor
? $this->resolveConstructorArgs($refConstructor)
: [];
$return = $refClass->newInstanceArgs($paramValues);
if ($save) {
$this->container->offsetSet($classname, $return);
return $return;
}
$paramValues = $this->resolveConstructorArgs($refConstructor);
$obj = $refClass->newInstanceArgs($paramValues);
if ($addToContainer) {
$this->container->offsetSet($classname, $obj);
}
return $obj;
return $return;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/CurlHttpMessage/AbstractClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ abstract class AbstractClient
*
* @throws InvalidArgumentException
*/
public function __construct($options = array())
public function __construct(array $options = array())
{
$cookieJarDefault = \tempnam(\sys_get_temp_dir(), 'curlHttpMessageCookies_') . '.txt';
$this->isTempCookieJar = isset($options['curl'][CURLOPT_COOKIEJAR]) === false;
Expand Down
8 changes: 4 additions & 4 deletions src/CurlHttpMessage/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Factory
*
* @param array $factories factory definitions
*/
public function __construct($factories = array())
public function __construct(array $factories = array())
{
$this->factories = \array_merge(array(
'curlReqRes' => [$this, 'buildCurlReqRes'],
Expand Down Expand Up @@ -82,7 +82,7 @@ public function __call($method, array $args)
*
* @return CurlReqRes
*/
public function buildCurlReqRes(RequestInterface $request, $options = array())
public function buildCurlReqRes(RequestInterface $request, array $options = array())
{
$curlReqRes = new CurlReqRes($request, $this->factories['response']);
$curlReqRes->setOptions($options);
Expand All @@ -100,7 +100,7 @@ public function buildCurlReqRes(RequestInterface $request, $options = array())
*
* @return Request
*/
public function buildRequest($method, $uri, $headers = array(), $body = null)
public function buildRequest($method, $uri, array $headers = array(), $body = null)
{
$request = new Request($method, $uri);
$request = $this->withHeaders($request, $headers);
Expand All @@ -119,7 +119,7 @@ public function buildRequest($method, $uri, $headers = array(), $body = null)
*
* @return Response
*/
public function buildResponse($code = 200, $reasonPhrase = '', $headers = array(), $body = null)
public function buildResponse($code = 200, $reasonPhrase = '', array $headers = array(), $body = null)
{
$response = new Response($code, (string) $reasonPhrase);
$response = $this->withHeaders($response, $headers);
Expand Down
2 changes: 1 addition & 1 deletion src/CurlHttpMessage/Handler/CurlMulti.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class CurlMulti extends Curl
*
* @throws RuntimeException
*/
public function __construct($options = array())
public function __construct(array $options = array())
{
$this->options = \array_replace_recursive(array(
'curlMulti' => array(),
Expand Down
4 changes: 2 additions & 2 deletions src/Debug/AbstractDebug.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ abstract class AbstractDebug
*
* @param array $cfg config
*/
public function __construct($cfg = array())
public function __construct(array $cfg = array())
{
if (!isset(self::$instance)) {
// self::getInstance() will always return initial/first instance
Expand All @@ -80,7 +80,7 @@ public function __call($methodName, array $args)
$this->publishBubbleEvent(Debug::EVENT_CUSTOM_METHOD, $logEntry);
if ($logEntry['handled'] !== true) {
$logEntry->setMeta('isCustomMethod', true);
$this->rootInstance->getPlugin('methodBasic')->log($logEntry);
$this->rootInstance->log($logEntry);
}
return $logEntry['return'];
}
Expand Down
52 changes: 19 additions & 33 deletions src/Debug/Abstraction/AbstractObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use bdk\Debug\Abstraction\Object\Properties;
use bdk\Debug\Abstraction\Object\PropertiesInstance;
use bdk\Debug\Abstraction\Object\Subscriber;
use bdk\Table\Element;
use ReflectionClass;
use ReflectionEnumUnitCase;
use RuntimeException;
Expand Down Expand Up @@ -181,11 +182,10 @@ class AbstractObject extends AbstractComponent
'keys' => array(),
// methods may be populated with __toString info, or methods with staticVars
'properties' => array(),
'scopeClass' => '',
'scopeClass' => null,
'sectionOrder' => array(), // cfg.objectSectionOrder
'sort' => '', // cfg.objectSort
'stringified' => null,
'traverseValues' => array(), // populated if method is table
'viaDebugInfo' => false,
);

Expand All @@ -205,10 +205,11 @@ public function __construct(Abstracter $abstracter)
$this->propertiesInstance = new PropertiesInstance($this);
$this->definition = new Definition($this);

if ($abstracter->debug->parentInstance === null) {
// we only need to subscribe to these events from root channel
$abstracter->debug->eventManager->addSubscriberInterface(new Subscriber($this));
}
// if we are the root instance, subscribe to events
// otherwise ensure root instance is instantiated
$abstracter->debug->parentInstance === null
? $abstracter->debug->eventManager->addSubscriberInterface(new Subscriber($this))
: $abstracter->debug->rootInstance->abstracter;

self::$values['sectionOrder'] = $abstracter->getCfg('objectSectionOrder');
self::$values['sort'] = $abstracter->getCfg('objectSort');
Expand All @@ -221,7 +222,7 @@ public function __construct(Abstracter $abstracter)
* @param string $method Method requesting abstraction
* @param array $hist (@internal) array & object history
*
* @return ObjectAbstraction
* @return ObjectAbstraction|mixed
* @throws RuntimeException
*/
public function getAbstraction($obj, $method = null, array $hist = array())
Expand All @@ -236,6 +237,11 @@ public function getAbstraction($obj, $method = null, array $hist = array())
$abs->setSubject($obj);
$abs['hist'][] = $obj;
$this->doAbstraction($abs);
if ($abs['unstructuredValue']) {
return $abs['unstructuredValue'];
}
// Mark definition as used
$this->definition->markAsUsed($definitionValueStore);
return $abs->clean();
}

Expand All @@ -254,26 +260,9 @@ public static function buildValues(array $values = array())
return $carry | $val;
}, 0) & ~self::BRIEF & ~self::PROP_VIRTUAL_VALUE_COLLECT;
}
return \array_merge(self::$values, $values);
}

/**
* Populate rows or columns (traverseValues) if we're outputting as a table
*
* @param ObjectAbstraction $abs Abstraction instance
*
* @return void
*/
private function addTraverseValues(ObjectAbstraction $abs)
{
if ($abs['traverseValues']) {
return;
}
$obj = $abs->getSubject();
$abs['hist'][] = $obj;
foreach ($obj as $k => $v) {
$abs['traverseValues'][$k] = $this->abstracter->crate($v, $abs['debugMethod'], $abs['hist']);
}
$values = \array_merge(self::$values, $values);
\ksort($values);
return $values;
}

/**
Expand All @@ -289,23 +278,18 @@ private function doAbstraction(ObjectAbstraction $abs)
if ($abs['isMaxDepth'] || $abs['isRecursion']) {
return;
}
$abs['isTraverseOnly'] = $this->helper->isTraverseOnly($abs);
/*
Debug::EVENT_OBJ_ABSTRACT_START subscriber may
set isExcluded
set collectPropertyValues (boolean)
set cfgFlags (int / bitmask)
set propertyOverrideValues
set stringified
set traverseValues
*/
$this->debug->publishBubbleEvent(Debug::EVENT_OBJ_ABSTRACT_START, $abs, $this->debug);
if ($abs['isExcluded']) {
return;
}
if ($abs['isTraverseOnly']) {
$this->addTraverseValues($abs);
}
$this->methods->addInstance($abs); // method static variables
$this->propertiesInstance->add($abs);
/*
Expand Down Expand Up @@ -347,7 +331,6 @@ protected function getAbstractionValues(ReflectionClass $reflector, $obj, $metho
'collectPropertyValues' => true,
'fullyQualifyPhpDocType' => $this->cfg['fullyQualifyPhpDocType'],
'hist' => $hist,
'isTraverseOnly' => false,
'propertyOverrideValues' => array(),
'reflector' => $reflector,
)
Expand Down Expand Up @@ -394,6 +377,9 @@ protected function getCfgFlags(ReflectionClass $reflector)
private function getScopeClass(array &$hist)
{
for ($i = \count($hist) - 1; $i >= 0; $i--) {
if ($hist[$i] instanceof Element) {
continue;
}
if (\is_object($hist[$i])) {
return \get_class($hist[$i]);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Debug/Abstraction/AbstractString.php
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,8 @@ private function getTypeMore($val)
return Type::TYPE_STRING_FILEPATH;
}
$strLen = \strlen($val);
$maxlen = $this->getMaxLen('other', $strLen);
return $maxlen > -1 && $strLen > $maxlen
$maxLen = $this->getMaxLen('other', $strLen);
return $maxLen > -1 && $strLen > $maxLen
? Type::TYPE_STRING_LONG
: null;
}
Expand Down
Loading