Skip to content

Commit

Permalink
Throw on bad/already deprecated seed (#326)
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek committed Sep 29, 2021
1 parent 462fcf8 commit 7b9eb05
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 96 deletions.
101 changes: 16 additions & 85 deletions src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,62 +22,6 @@ final protected static function getInstance(): self
return self::$_instance;
}

protected function printDeprecatedWarningWithTrace(string $msg): void // remove once not used within this class
{
static $traceRenderer = null;
if ($traceRenderer === null) {
$traceRenderer = new class(new Exception()) extends ExceptionRenderer\Html {
public function tryRelativizePath(string $path): string
{
try {
return $this->makeRelativePath($path);
} catch (Exception $e) {
}

return $path;
}
};
}

ob_start();
debug_print_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
$trace = preg_replace('~^#0.+?\n~', '', ob_get_clean());
$trace = preg_replace_callback('~[^\n\[\]<>]+\.php~', function ($matches) use ($traceRenderer) {
return $traceRenderer->tryRelativizePath($matches[0]);
}, $trace);
// echo (new Exception($msg))->getHtml();
'trigger_error'($msg . (!class_exists(\PHPUnit\Framework\Test::class, false) ? "\n" . $trace : ''), \E_USER_DEPRECATED);
}

/**
* @param mixed $seed
*/
private function checkSeeFunc($seed): ?string
{
if (is_object($seed) || $seed === null) {
return null;
} elseif (!array_key_exists(0, $seed)) {
return null; // 'not defined' allow this method to be used to merge seeds without class name
} elseif ($seed[0] === null) {
return null;
} elseif (!is_string($seed[0])) {
return 'invalid type (' . (is_object($seed[0]) ? get_class($seed[0]) . ' (class wrapped in an array?)' : gettype($seed[0])) . ')';
} elseif (class_exists($seed[0])) {
return null;
}

// do not emit warnings for core tests:
// - some tests already tests for exception
// - we may later want to use this function for "mergeDefaults" (like _factory() below does)
foreach (debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) {
if (strpos($frame['class'] ?? '', 'Atk4\Core\Tests\\') === 0) {
return null;
}
}

return 'non-existing/non-autoloadable (' . $seed[0] . ')';
}

/**
* @param array|object|null ...$seeds
*
Expand All @@ -95,7 +39,7 @@ protected function _mergeSeeds(...$seeds)
if (is_object($seed)) {
if ($obj !== null) {
continue; // legacy behaviour
// throw new \Exception('Two or more objects specified as seed.');
// throw new Exception('Two or more objects specified as seed');
}

$obj = $seed;
Expand All @@ -108,13 +52,16 @@ protected function _mergeSeeds(...$seeds)
continue;
}

if ($this->checkSeeFunc($seed) !== null) {
// remove/do not accept other seed than object/array type after 2020-dec
// remove/do not accept seed with 1st argument other than valid class name (or null) after 2020-dec
$this->printDeprecatedWarningWithTrace(
'Use of invalid/deprecated $seed' . $seedIndex . ' class name (' . $this->checkSeeFunc($seed) . '). Support will be removed shortly.'
);
}
// check seed
if (!array_key_exists(0, $seed)) {
// allow this method to be used to merge seeds without class name
} elseif ($seed[0] === null) {
// pass
} elseif (!is_string($seed[0])) {
throw new Exception('Seed class type (' . get_debug_type($seed[0]) . ') must be string');
} /*elseif (!class_exists($seed[0])) {
throw new Exception('Seed class "' . $seed[0] . '" not found');
}*/

if (!is_array($seed)) {
$seed = [$seed];
Expand Down Expand Up @@ -176,44 +123,28 @@ protected function _newObject(string $className, array $ctorArgs): object

/**
* @param array|object $seed
* @param array $defaults
*/
protected function _factory($seed, $defaults = []): object
protected function _factory($seed, array $defaults = null): object
{
if (is_object($defaults)) {
throw new Exception('Factory $defaults can not be an object');
}

if ($defaults === null) { // should be deprecated soon
if ($defaults === null) { // should be deprecated soon (with [] default value)
$defaults = [];
}

if ($seed === null) { // should be deprecated soon
$seed = [];
}

if ((!is_array($seed) && !is_object($seed)) || (!is_array($defaults) && !is_object($defaults))) { // remove/do not accept other seed than object/array type after 2020-dec
$varName = !is_array($seed) && !is_object($seed) ? 'seed' : 'defaults';
$this->printDeprecatedWarningWithTrace(
'Use of non-array seed ($' . $varName . ' type = ' . gettype(${$varName}) . ') is deprecated and support will be removed shortly.'
);
if ((!is_array($seed) && !is_object($seed))) {
throw new Exception('Use of non-array seed ($seed type = ' . gettype($seed) . ') is not supported.');
}

if (is_array($defaults)) {
array_unshift($defaults, null); // insert argument 0
} else {
$defaults = [null, $defaults];
}
array_unshift($defaults, null); // insert argument 0

if (is_object($seed)) {
$defaults = $this->_mergeSeeds([], $defaults);
$defaults[0] = $seed;
$seed = $defaults;
} else {
if (!is_array($seed)) {
$seed = [$seed];
}

$seed = $this->_mergeSeeds($seed, $defaults);
}
unset($defaults);
Expand Down
4 changes: 1 addition & 3 deletions src/StaticAddToTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ private static function _addTo_add(object $parent, object $object, array $addArg
* $crud = $app->add(['Crud', 'displayFields' => ['name']]);
* but the first one design pattern is strongly recommended as it supports refactoring.
*
* @param array $seed
*
* @return static
*/
public static function addTo(object $parent, $seed = [], array $addArgs = [], bool $skipAdd = false)// :static supported by PHP8+
public static function addTo(object $parent, array $seed = [], array $addArgs = [], bool $skipAdd = false)// :static supported by PHP8+
{
$object = static::fromSeed([static::class], $seed);

Expand Down
11 changes: 4 additions & 7 deletions tests/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,7 @@ public function testNull(): void

public function testDefaultsObject(): void
{
// $this->expectException(Exception::class);
$this->expectDeprecation(); // replace with line above once support is removed (expected in 2020-dec)
$this->expectException(Exception::class);
$s1 = Factory::factory([new FactoryTestDiMock(), 'foo' => 'bar'], ['baz' => '', 'foo' => 'default']);
}

Expand Down Expand Up @@ -354,7 +353,7 @@ public function testMustHaveProperty(): void

public function testGiveClassFirst(): void
{
$this->expectException(Exception::class);
$this->expectException(\TypeError::class);
$s1 = Factory::factory(['foo' => 'bar'], new FactoryTestDiMock()); // @phpstan-ignore-line
}

Expand Down Expand Up @@ -412,8 +411,7 @@ public function testFactory(): void
$this->assertSame(FactoryFactoryMock::class, get_class($m1));

// from string seed
// $this->expectException(Exception::class);
$this->expectDeprecation(); // replace with line above once support is removed (expected in 2020-dec)
$this->expectException(Exception::class);
Factory::factory(FactoryFactoryMock::class); // @phpstan-ignore-line
}

Expand Down Expand Up @@ -477,8 +475,7 @@ public function testFactoryParameters(): void
$this->assertSame('ZZZ', $m2->c);

// as object wrapped in array
// $this->expectException(Exception::class);
$this->expectDeprecation(); // replace with line above once support is removed (expected in 2020-dec)
$this->expectException(Exception::class);
Factory::factory([$m1]);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/StaticAddToTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function testBasic(): void
$this->assertSame($tr, $tr3);

// not the same or extended class
$this->expectException(\Atk4\Core\Exception::class);
$this->expectException(\TypeError::class);
$tr = StdSat::addTo($m, $tr); // @phpstan-ignore-line
}

Expand Down

0 comments on commit 7b9eb05

Please sign in to comment.