Skip to content

Commit

Permalink
API TableBuilder class reduces inconsistency between temp & prod db
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli committed Jul 6, 2022
1 parent 33600c3 commit 29fae72
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 62 deletions.
69 changes: 69 additions & 0 deletions src/ORM/Connect/TableBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace SilverStripe\ORM\Connect;

use SilverStripe\Control\Director;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;

class TableBuilder
{
use Injectable;

public function buildTables(DBSchemaManager $dbSchema, array $dataClasses, array $extraDataObjects = [], bool $quiet = false, bool $testMode = false, bool $showRecordCounts = false)
{
$dbSchema->schemaUpdate(function () use ($dataClasses, $extraDataObjects, $testMode, $quiet, $showRecordCounts) {
$dataObjectSchema = DataObject::getSchema();

foreach ($dataClasses as $dataClass) {
// Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
if (!class_exists($dataClass)) {
continue;
}

// Check if this class should be excluded as per testing conventions
/** @var DataObject $SNG */
$SNG = new $dataClass([], DataObject::CREATE_SINGLETON);
if (!$testMode && $SNG instanceof TestOnly) {
continue;
}

// Log data
if (!$quiet) {
$tableName = $dataObjectSchema->tableName($dataClass);
if ($showRecordCounts && DB::get_schema()->hasTable($tableName)) {
try {
$count = DB::query("SELECT COUNT(*) FROM \"$tableName\"")->value();
$countSuffix = " ($count records)";
} catch (\Exception $e) {
$countSuffix = " (error getting record count)";
}
} else {
$countSuffix = "";
}

if (Director::is_cli()) {
echo " * $tableName$countSuffix\n";
} else {
echo "<li>$tableName$countSuffix</li>\n";
}
}

// Instruct the class to apply its schema to the database
$SNG->requireTable();
}

// If we have additional dataobjects which need schema (i.e. for tests), do so here:
if ($extraDataObjects) {
foreach ($extraDataObjects as $dataClass) {
$SNG = new $dataClass([], DataObject::CREATE_SINGLETON);
if ($SNG instanceof DataObject) {
$SNG->requireTable();
}
}
}
});
}
}
24 changes: 2 additions & 22 deletions src/ORM/Connect/TempDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,29 +244,9 @@ protected function rebuildTables($extraDataObjects = [])

$schema = $this->getConn()->getSchemaManager();
$schema->quiet();
$schema->schemaUpdate(
function () use ($dataClasses, $extraDataObjects) {
foreach ($dataClasses as $dataClass) {
// Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
if (class_exists($dataClass ?? '')) {
$SNG = singleton($dataClass);
if (!($SNG instanceof TestOnly)) {
$SNG->requireTable();
}
}
}

// If we have additional dataobjects which need schema, do so here:
if ($extraDataObjects) {
foreach ($extraDataObjects as $dataClass) {
$SNG = singleton($dataClass);
if (singleton($dataClass) instanceof DataObject) {
$SNG->requireTable();
}
}
}
}
);
$tableBuilder = TableBuilder::singleton();
$tableBuilder->buildTables($schema, $dataClasses, $extraDataObjects, true);

Config::modify()->set(DBSchemaManager::class, 'check_and_repair_on_build', $oldCheckAndRepairOnBuild);

Expand Down
43 changes: 3 additions & 40 deletions src/ORM/DatabaseAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use SilverStripe\Dev\DevelopmentAdmin;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\Connect\DatabaseException;
use SilverStripe\ORM\Connect\TableBuilder;
use SilverStripe\ORM\FieldType\DBClassName;
use SilverStripe\Security\Permission;
use SilverStripe\Security\Security;
Expand Down Expand Up @@ -304,46 +305,8 @@ public function doBuild($quiet = false, $populate = true, $testMode = false)

// Initiate schema update
$dbSchema = DB::get_schema();
$dbSchema->schemaUpdate(function () use ($dataClasses, $testMode, $quiet, $showRecordCounts) {
$dataObjectSchema = DataObject::getSchema();

foreach ($dataClasses as $dataClass) {
// Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
if (!class_exists($dataClass ?? '')) {
continue;
}

// Check if this class should be excluded as per testing conventions
$SNG = new $dataClass([], DataObject::CREATE_SINGLETON);
if (!$testMode && $SNG instanceof TestOnly) {
continue;
}
$tableName = $dataObjectSchema->tableName($dataClass);

// Log data
if (!$quiet) {
if ($showRecordCounts && DB::get_schema()->hasTable($tableName)) {
try {
$count = DB::query("SELECT COUNT(*) FROM \"$tableName\"")->value();
$countSuffix = " ($count records)";
} catch (Exception $e) {
$countSuffix = " (error getting record count)";
}
} else {
$countSuffix = "";
}

if (Director::is_cli()) {
echo " * $tableName$countSuffix\n";
} else {
echo "<li>$tableName$countSuffix</li>\n";
}
}

// Instruct the class to apply its schema to the database
$SNG->requireTable();
}
});
$tableBuilder = TableBuilder::singleton();
$tableBuilder->buildTables($dbSchema, $dataClasses, [], $quiet, $testMode, $showRecordCounts);
ClassInfo::reset_db_cache();

if (!$quiet && !Director::is_cli()) {
Expand Down

0 comments on commit 29fae72

Please sign in to comment.