silverstripe-framework/src/Dev/State/ExtensionTestState.php

125 lines
4.2 KiB
PHP

<?php
namespace SilverStripe\Dev\State;
use LogicException;
use SilverStripe\Core\Extension;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\DataObject;
/**
* Manages illegal and required extensions for sapphiretest
*/
class ExtensionTestState implements TestState
{
/**
* @var array
*/
protected $extensionsToReapply = [];
/**
* @var array
*/
protected $extensionsToRemove = [];
/**
* Called on setup
*
* @param SapphireTest $test
*/
public function setUp(SapphireTest $test)
{
}
public function tearDown(SapphireTest $test)
{
}
public function setUpOnce($class)
{
// May be altered by another class
$isAltered = false;
$this->extensionsToReapply = [];
$this->extensionsToRemove = [];
/** @var string|SapphireTest $class */
/** @var string|DataObject $dataClass */
// Remove any illegal extensions that are present
foreach ($class::getIllegalExtensions() as $dataClass => $extensions) {
if (!class_exists($dataClass)) {
continue;
}
if ($extensions === '*') {
$extensions = $dataClass::get_extensions();
}
foreach ($extensions as $extension) {
if (!class_exists($extension) || !$dataClass::has_extension($extension)) {
continue;
}
if (!isset($this->extensionsToReapply[$dataClass])) {
$this->extensionsToReapply[$dataClass] = [];
}
$this->extensionsToReapply[$dataClass][] = $extension;
$dataClass::remove_extension($extension);
$isAltered = true;
}
}
// Add any required extensions that aren't present
foreach ($class::getRequiredExtensions() as $dataClass => $extensions) {
if (!class_exists($dataClass)) {
throw new LogicException("Test {$class} requires dataClass {$dataClass} which doesn't exist");
}
foreach ($extensions as $extension) {
$extension = Extension::get_classname_without_arguments($extension);
if (!class_exists($extension)) {
throw new LogicException("Test {$class} requires extension {$extension} which doesn't exist");
}
if (!$dataClass::has_extension($extension)) {
if (!isset($this->extensionsToRemove[$dataClass])) {
$this->extensionsToRemove[$dataClass] = [];
}
$this->extensionsToRemove[$dataClass][] = $extension;
$dataClass::add_extension($extension);
$isAltered = true;
}
}
}
// clear singletons, they're caching old extension info
// which is used in DatabaseAdmin->doBuild()
Injector::inst()->unregisterObjects(DataObject::class);
// If we have altered the schema, but SapphireTest::setUpBeforeClass() would not otherwise
// reset the schema (if there were extra objects) then force a reset
if ($isAltered && empty($class::getExtraDataObjects())) {
DataObject::reset();
$class::resetDBSchema(true, true);
}
}
public function tearDownOnce($class)
{
// @todo: This isn't strictly necessary to restore extensions, but only to ensure that
// Object::$extra_methods is properly flushed. This should be replaced with a simple
// flush mechanism for each $class.
/** @var string|DataObject $dataClass */
// Remove extensions added for testing
foreach ($this->extensionsToRemove as $dataClass => $extensions) {
foreach ($extensions as $extension) {
$dataClass::remove_extension($extension);
}
}
// Reapply ones removed
foreach ($this->extensionsToReapply as $dataClass => $extensions) {
foreach ($extensions as $extension) {
$dataClass::add_extension($extension);
}
}
}
}