Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F18409081
D10496.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
30 KB
Referenced Files
None
Subscribers
None
D10496.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1360,9 +1360,11 @@
'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php',
'PhabricatorConfigResponse' => 'applications/config/response/PhabricatorConfigResponse.php',
'PhabricatorConfigSchemaQuery' => 'applications/config/schema/PhabricatorConfigSchemaQuery.php',
+ 'PhabricatorConfigSchemaSpec' => 'applications/config/schema/PhabricatorConfigSchemaSpec.php',
'PhabricatorConfigServerSchema' => 'applications/config/schema/PhabricatorConfigServerSchema.php',
'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php',
'PhabricatorConfigStackSource' => 'infrastructure/env/PhabricatorConfigStackSource.php',
+ 'PhabricatorConfigStorageSchema' => 'applications/config/schema/PhabricatorConfigStorageSchema.php',
'PhabricatorConfigTableSchema' => 'applications/config/schema/PhabricatorConfigTableSchema.php',
'PhabricatorConfigTransaction' => 'applications/config/storage/PhabricatorConfigTransaction.php',
'PhabricatorConfigTransactionQuery' => 'applications/config/query/PhabricatorConfigTransactionQuery.php',
@@ -4216,11 +4218,11 @@
'PhabricatorConduitTokenController' => 'PhabricatorConduitController',
'PhabricatorConfigAllController' => 'PhabricatorConfigController',
'PhabricatorConfigApplication' => 'PhabricatorApplication',
- 'PhabricatorConfigColumnSchema' => 'Phobject',
+ 'PhabricatorConfigColumnSchema' => 'PhabricatorConfigStorageSchema',
'PhabricatorConfigConfigPHIDType' => 'PhabricatorPHIDType',
'PhabricatorConfigController' => 'PhabricatorController',
'PhabricatorConfigDatabaseController' => 'PhabricatorConfigController',
- 'PhabricatorConfigDatabaseSchema' => 'Phobject',
+ 'PhabricatorConfigDatabaseSchema' => 'PhabricatorConfigStorageSchema',
'PhabricatorConfigDatabaseSource' => 'PhabricatorConfigProxySource',
'PhabricatorConfigDefaultSource' => 'PhabricatorConfigProxySource',
'PhabricatorConfigDictionarySource' => 'PhabricatorConfigSource',
@@ -4252,9 +4254,11 @@
'PhabricatorConfigProxySource' => 'PhabricatorConfigSource',
'PhabricatorConfigResponse' => 'AphrontHTMLResponse',
'PhabricatorConfigSchemaQuery' => 'Phobject',
- 'PhabricatorConfigServerSchema' => 'Phobject',
+ 'PhabricatorConfigSchemaSpec' => 'Phobject',
+ 'PhabricatorConfigServerSchema' => 'PhabricatorConfigStorageSchema',
'PhabricatorConfigStackSource' => 'PhabricatorConfigSource',
- 'PhabricatorConfigTableSchema' => 'Phobject',
+ 'PhabricatorConfigStorageSchema' => 'Phobject',
+ 'PhabricatorConfigTableSchema' => 'PhabricatorConfigStorageSchema',
'PhabricatorConfigTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorConfigValidationException' => 'Exception',
diff --git a/src/applications/config/application/PhabricatorConfigApplication.php b/src/applications/config/application/PhabricatorConfigApplication.php
--- a/src/applications/config/application/PhabricatorConfigApplication.php
+++ b/src/applications/config/application/PhabricatorConfigApplication.php
@@ -42,7 +42,10 @@
'edit/(?P<key>[\w\.\-]+)/' => 'PhabricatorConfigEditController',
'group/(?P<key>[^/]+)/' => 'PhabricatorConfigGroupController',
'welcome/' => 'PhabricatorConfigWelcomeController',
- 'database/(?:(?P<database>[^/]+)/(?:(?P<table>[^/]+)/)?)?'
+ 'database/'.
+ '(?:(?P<database>[^/]+)/'.
+ '(?:(?P<table>[^/]+)/'.
+ '(?:(?P<column>[^/]+)/)?)?)?'
=> 'PhabricatorConfigDatabaseController',
'(?P<verb>ignore|unignore)/(?P<key>[^/]+)/'
=> 'PhabricatorConfigIgnoreController',
diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseController.php b/src/applications/config/controller/PhabricatorConfigDatabaseController.php
--- a/src/applications/config/controller/PhabricatorConfigDatabaseController.php
+++ b/src/applications/config/controller/PhabricatorConfigDatabaseController.php
@@ -5,10 +5,12 @@
private $database;
private $table;
+ private $column;
public function willProcessRequest(array $data) {
$this->database = idx($data, 'database');
$this->table = idx($data, 'table');
+ $this->column = idx($data, 'column');
}
public function processRequest() {
@@ -31,22 +33,34 @@
$actual = $query->loadActualSchema();
$expect = $query->loadExpectedSchema();
+ $comp = $query->buildComparisonSchema($expect, $actual);
- if ($this->table) {
- return $this->renderTable(
+ if ($this->column) {
+ return $this->renderColumn(
+ $comp,
+ $expect,
$actual,
+ $this->database,
+ $this->table,
+ $this->column);
+ } else if ($this->table) {
+ return $this->renderTable(
+ $comp,
$expect,
+ $actual,
$this->database,
$this->table);
} else if ($this->database) {
return $this->renderDatabase(
- $actual,
+ $comp,
$expect,
+ $actual,
$this->database);
} else {
return $this->renderServer(
- $actual,
- $expect);
+ $comp,
+ $expect,
+ $actual);
}
}
@@ -83,41 +97,29 @@
private function renderServer(
- PhabricatorConfigServerSchema $schema,
- PhabricatorConfigServerSchema $expect) {
-
- $icon_ok = id(new PHUIIconView())
- ->setIconFont('fa-check-circle green');
+ PhabricatorConfigServerSchema $comp,
+ PhabricatorConfigServerSchema $expect,
+ PhabricatorConfigServerSchema $actual) {
- $icon_warn = id(new PHUIIconView())
- ->setIconFont('fa-exclamation-circle yellow');
+ $charset_issue = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
+ $collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
$rows = array();
- foreach ($schema->getDatabases() as $database_name => $database) {
-
- $expect_database = $expect->getDatabase($database_name);
- if ($expect_database) {
- $expect_set = $expect_database->getCharacterSet();
- $expect_collation = $expect_database->getCollation();
-
- if ($database->isSameSchema($expect_database)) {
- $icon = $icon_ok;
- } else {
- $icon = $icon_warn;
- }
+ foreach ($comp->getDatabases() as $database_name => $database) {
+ $actual_database = $actual->getDatabase($database_name);
+ if ($actual_database) {
+ $charset = $actual_database->getCharacterSet();
+ $collation = $actual_database->getCollation();
} else {
- $expect_set = null;
- $expect_collation = null;
- $icon = $icon_warn;
+ $charset = null;
+ $collation = null;
}
- $actual_set = $database->getCharacterSet();
- $actual_collation = $database->getCollation();
-
-
+ $status = $database->getStatus();
+ $issues = $database->getIssues();
$rows[] = array(
- $icon,
+ $this->renderIcon($status),
phutil_tag(
'a',
array(
@@ -125,10 +127,8 @@
'/database/'.$database_name.'/'),
),
$database_name),
- $actual_set,
- $expect_set,
- $actual_collation,
- $expect_collation,
+ $this->renderAttr($charset, $database->hasIssue($charset_issue)),
+ $this->renderAttr($collation, $database->hasIssue($collation_issue)),
);
}
@@ -138,13 +138,11 @@
null,
pht('Database'),
pht('Charset'),
- pht('Expected Charset'),
pht('Collation'),
- pht('Expected Collation'),
))
->setColumnClasses(
array(
- '',
+ null,
'wide pri',
null,
null,
@@ -152,26 +150,38 @@
$title = pht('Database Status');
+ $properties = $this->buildProperties(
+ array(
+ ),
+ $comp->getIssues());
+
$box = id(new PHUIObjectBoxView())
->setHeaderText($title)
+ ->addPropertyList($properties)
->appendChild($table);
return $this->buildResponse($title, $box);
}
private function renderDatabase(
- PhabricatorConfigServerSchema $schema,
+ PhabricatorConfigServerSchema $comp,
PhabricatorConfigServerSchema $expect,
+ PhabricatorConfigServerSchema $actual,
$database_name) {
- $database = $schema->getDatabase($database_name);
+ $database = $comp->getDatabase($database_name);
if (!$database) {
return new Aphront404Response();
}
$rows = array();
foreach ($database->getTables() as $table_name => $table) {
+
+ $status = $table->getStatus();
+ $issues = $table->getIssues();
+
$rows[] = array(
+ $this->renderIcon($status),
phutil_tag(
'a',
array(
@@ -186,31 +196,74 @@
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
+ null,
pht('Table'),
pht('Collation'),
))
->setColumnClasses(
array(
+ null,
'wide pri',
null,
));
$title = pht('Database Status: %s', $database_name);
+ $actual_database = $actual->getDatabase($database_name);
+ if ($actual_database) {
+ $actual_charset = $actual_database->getCharacterSet();
+ $actual_collation = $actual_database->getCollation();
+ } else {
+ $actual_charset = null;
+ $actual_collation = null;
+ }
+
+ $expect_database = $expect->getDatabase($database_name);
+ if ($expect_database) {
+ $expect_charset = $expect_database->getCharacterSet();
+ $expect_collation = $expect_database->getCollation();
+ } else {
+ $expect_charset = null;
+ $expect_collation = null;
+ }
+
+ $properties = $this->buildProperties(
+ array(
+ array(
+ pht('Character Set'),
+ $actual_charset,
+ ),
+ array(
+ pht('Expected Character Set'),
+ $expect_charset,
+ ),
+ array(
+ pht('Collation'),
+ $actual_collation,
+ ),
+ array(
+ pht('Expected Collation'),
+ $expect_collation,
+ ),
+ ),
+ $database->getIssues());
+
$box = id(new PHUIObjectBoxView())
->setHeaderText($title)
+ ->addPropertyList($properties)
->appendChild($table);
return $this->buildResponse($title, $box);
}
private function renderTable(
- PhabricatorConfigServerSchema $schema,
+ PhabricatorConfigServerSchema $comp,
PhabricatorConfigServerSchema $expect,
+ PhabricatorConfigServerSchema $actual,
$database_name,
$table_name) {
- $database = $schema->getDatabase($database_name);
+ $database = $comp->getDatabase($database_name);
if (!$database) {
return new Aphront404Response();
}
@@ -222,17 +275,30 @@
$rows = array();
foreach ($table->getColumns() as $column_name => $column) {
+ $status = $column->getStatus();
+
$rows[] = array(
- $column_name,
+ $this->renderIcon($status),
+ phutil_tag(
+ 'a',
+ array(
+ 'href' => $this->getApplicationURI(
+ 'database/'.
+ $database_name.'/'.
+ $table_name.'/'.
+ $column_name.'/'),
+ ),
+ $column_name),
$column->getColumnType(),
$column->getCharacterSet(),
$column->getCollation(),
);
}
- $table = id(new AphrontTableView($rows))
+ $table_view = id(new AphrontTableView($rows))
->setHeaders(
array(
+ null,
pht('Table'),
pht('Column Type'),
pht('Character Set'),
@@ -240,6 +306,7 @@
))
->setColumnClasses(
array(
+ null,
'wide pri',
null,
null,
@@ -248,11 +315,133 @@
$title = pht('Database Status: %s.%s', $database_name, $table_name);
+ $properties = $this->buildProperties(
+ array(
+ ),
+ $table->getIssues());
+
$box = id(new PHUIObjectBoxView())
->setHeaderText($title)
- ->appendChild($table);
+ ->addPropertyList($properties)
+ ->appendChild($table_view);
+
+ return $this->buildResponse($title, $box);
+ }
+
+ private function renderColumn(
+ PhabricatorConfigServerSchema $comp,
+ PhabricatorConfigServerSchema $expect,
+ PhabricatorConfigServerSchema $actual,
+ $database_name,
+ $table_name,
+ $column_name) {
+
+ $database = $comp->getDatabase($database_name);
+ if (!$database) {
+ return new Aphront404Response();
+ }
+
+ $table = $database->getTable($table_name);
+ if (!$table) {
+ return new Aphront404Response();
+ }
+
+ $column = $table->getColumn($column_name);
+ if (!$table) {
+ return new Aphront404Response();
+ }
+
+ $title = pht(
+ 'Database Status: %s.%s.%s',
+ $database_name,
+ $table_name,
+ $column_name);
+
+ $properties = $this->buildProperties(
+ array(
+ ),
+ $column->getIssues());
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeaderText($title)
+ ->addPropertyList($properties);
return $this->buildResponse($title, $box);
}
+ private function renderIcon($status) {
+ switch ($status) {
+ case PhabricatorConfigStorageSchema::STATUS_OKAY:
+ $icon = 'fa-check-circle green';
+ break;
+ case PhabricatorConfigStorageSchema::STATUS_WARN:
+ $icon = 'fa-exclamation-circle yellow';
+ break;
+ case PhabricatorConfigStorageSchema::STATUS_FAIL:
+ default:
+ $icon = 'fa-times-circle red';
+ break;
+ }
+
+ return id(new PHUIIconView())
+ ->setIconFont($icon);
+ }
+
+ private function renderAttr($attr, $issue) {
+ if ($issue) {
+ return phutil_tag(
+ 'span',
+ array(
+ 'style' => 'color: #aa0000;',
+ ),
+ $attr);
+ } else {
+ return $attr;
+ }
+ }
+
+ private function buildProperties(array $properties, array $issues) {
+ $view = id(new PHUIPropertyListView())
+ ->setUser($this->getRequest()->getUser());
+
+ foreach ($properties as $property) {
+ list($key, $value) = $property;
+ $view->addProperty($key, $value);
+ }
+
+ $status_view = new PHUIStatusListView();
+ if (!$issues) {
+ $status_view->addItem(
+ id(new PHUIStatusItemView())
+ ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
+ ->setTarget(pht('No Schema Issues')));
+ } else {
+ foreach ($issues as $issue) {
+ $note = PhabricatorConfigStorageSchema::getIssueDescription($issue);
+
+ $status = PhabricatorConfigStorageSchema::getIssueStatus($issue);
+ switch ($status) {
+ case PhabricatorConfigStorageSchema::STATUS_WARN:
+ $icon = PHUIStatusItemView::ICON_WARNING;
+ $color = 'yellow';
+ break;
+ case PhabricatorConfigStorageSchema::STATUS_FAIL:
+ default:
+ $icon = PHUIStatusItemView::ICON_REJECT;
+ $color = 'red';
+ break;
+ }
+
+ $item = id(new PHUIStatusItemView())
+ ->setTarget(PhabricatorConfigStorageSchema::getIssueName($issue))
+ ->setIcon($icon, $color)
+ ->setNote($note);
+
+ $status_view->addItem($item);
+ }
+ }
+ $view->addProperty(pht('Schema Status'), $status_view);
+
+ return $view;
+ }
}
diff --git a/src/applications/config/schema/PhabricatorConfigColumnSchema.php b/src/applications/config/schema/PhabricatorConfigColumnSchema.php
--- a/src/applications/config/schema/PhabricatorConfigColumnSchema.php
+++ b/src/applications/config/schema/PhabricatorConfigColumnSchema.php
@@ -1,8 +1,8 @@
<?php
-final class PhabricatorConfigColumnSchema extends Phobject {
+final class PhabricatorConfigColumnSchema
+ extends PhabricatorConfigStorageSchema {
- private $name;
private $characterSet;
private $collation;
private $columnType;
@@ -16,6 +16,10 @@
return $this->columnType;
}
+ protected function getSubschemata() {
+ return array();
+ }
+
public function setCollation($collation) {
$this->collation = $collation;
return $this;
@@ -34,13 +38,28 @@
return $this->characterSet;
}
- public function setName($name) {
- $this->name = $name;
- return $this;
+ public function compareToSimilarSchema(
+ PhabricatorConfigStorageSchema $expect) {
+
+ $issues = array();
+ if ($this->getCharacterSet() != $expect->getCharacterSet()) {
+ $issues[] = self::ISSUE_CHARSET;
+ }
+
+ if ($this->getCollation() != $expect->getCollation()) {
+ $issues[] = self::ISSUE_COLLATION;
+ }
+
+ if ($this->getColumnType() != $expect->getColumnType()) {
+ $issues[] = self::ISSUE_COLUMNTYPE;
+ }
+
+ return $issues;
}
- public function getName() {
- return $this->name;
+ public function newEmptyClone() {
+ $clone = clone $this;
+ return $clone;
}
}
diff --git a/src/applications/config/schema/PhabricatorConfigDatabaseSchema.php b/src/applications/config/schema/PhabricatorConfigDatabaseSchema.php
--- a/src/applications/config/schema/PhabricatorConfigDatabaseSchema.php
+++ b/src/applications/config/schema/PhabricatorConfigDatabaseSchema.php
@@ -1,8 +1,8 @@
<?php
-final class PhabricatorConfigDatabaseSchema extends Phobject {
+final class PhabricatorConfigDatabaseSchema
+ extends PhabricatorConfigStorageSchema {
- private $name;
private $characterSet;
private $collation;
private $tables = array();
@@ -25,16 +25,29 @@
return idx($this->tables, $key);
}
- public function isSameSchema(PhabricatorConfigDatabaseSchema $expect) {
- return ($this->toDictionary() === $expect->toDictionary());
+ protected function getSubschemata() {
+ return $this->getTables();
}
- public function toDictionary() {
- return array(
- 'name' => $this->getName(),
- 'characterSet' => $this->getCharacterSet(),
- 'collation' => $this->getCollation(),
- );
+ public function compareToSimilarSchema(
+ PhabricatorConfigStorageSchema $expect) {
+
+ $issues = array();
+ if ($this->getCharacterSet() != $expect->getCharacterSet()) {
+ $issues[] = self::ISSUE_CHARSET;
+ }
+
+ if ($this->getCollation() != $expect->getCollation()) {
+ $issues[] = self::ISSUE_COLLATION;
+ }
+
+ return $issues;
+ }
+
+ public function newEmptyClone() {
+ $clone = clone $this;
+ $clone->tables = array();
+ return $clone;
}
public function setCollation($collation) {
@@ -55,13 +68,4 @@
return $this->characterSet;
}
- public function setName($name) {
- $this->name = $name;
- return $this;
- }
-
- public function getName() {
- return $this->name;
- }
-
}
diff --git a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
--- a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
+++ b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
@@ -92,7 +92,6 @@
return $server_schema;
}
-
public function loadExpectedSchema() {
$databases = $this->getDatabaseNames();
@@ -119,17 +118,101 @@
$utf8_collate = 'binary';
}
+ $specs = id(new PhutilSymbolLoader())
+ ->setAncestorClass('PhabricatorConfigSchemaSpec')
+ ->loadObjects();
+
$server_schema = new PhabricatorConfigServerSchema();
- foreach ($databases as $database_name) {
- $database_schema = id(new PhabricatorConfigDatabaseSchema())
- ->setName($database_name)
- ->setCharacterSet($utf8_charset)
- ->setCollation($utf8_collate);
+ foreach ($specs as $spec) {
+ $spec->setUTF8Charset($utf8_charset);
+ $spec->setUTF8Collate($utf8_collate);
- $server_schema->addDatabase($database_schema);
+ $spec->buildSchemata($server_schema);
}
return $server_schema;
}
+ public function buildComparisonSchema(
+ PhabricatorConfigServerSchema $expect,
+ PhabricatorConfigServerSchema $actual) {
+
+ $comp_server = $actual->newEmptyClone();
+
+ $all_databases = $actual->getDatabases() + $expect->getDatabases();
+ foreach ($all_databases as $database_name => $database_template) {
+ $actual_database = $actual->getDatabase($database_name);
+ $expect_database = $expect->getDatabase($database_name);
+
+ $issues = $this->compareSchemata($expect_database, $actual_database);
+
+ $comp_database = $database_template->newEmptyClone()
+ ->setIssues($issues);
+
+ if (!$actual_database) {
+ $actual_database = $expect_database->newEmptyClone();
+ }
+ if (!$expect_database) {
+ $expect_database = $actual_database->newEmptyClone();
+ }
+
+ $all_tables =
+ $actual_database->getTables() +
+ $expect_database->getTables();
+ foreach ($all_tables as $table_name => $table_template) {
+ $actual_table = $actual_database->getTable($table_name);
+ $expect_table = $expect_database->getTable($table_name);
+
+ $issues = $this->compareSchemata($expect_table, $actual_table);
+
+ $comp_table = $table_template->newEmptyClone()
+ ->setIssues($issues);
+
+ if (!$actual_table) {
+ $actual_table = $expect_table->newEmptyClone();
+ }
+ if (!$expect_table) {
+ $expect_table = $actual_table->newEmptyClone();
+ }
+
+ $all_columns =
+ $actual_table->getColumns() +
+ $expect_table->getColumns();
+ foreach ($all_columns as $column_name => $column_template) {
+ $actual_column = $actual_table->getColumn($column_name);
+ $expect_column = $expect_table->getColumn($column_name);
+
+ $issues = $this->compareSchemata($expect_column, $actual_column);
+
+ $comp_column = $column_template->newEmptyClone()
+ ->setIssues($issues);
+
+ $comp_table->addColumn($comp_column);
+ }
+ $comp_database->addTable($comp_table);
+ }
+ $comp_server->addDatabase($comp_database);
+ }
+
+ return $comp_server;
+ }
+
+ private function compareSchemata(
+ PhabricatorConfigStorageSchema $expect = null,
+ PhabricatorConfigStorageSchema $actual = null) {
+
+ if (!$expect && !$actual) {
+ throw new Exception(pht('Can not compare two missing schemata!'));
+ } else if ($expect && !$actual) {
+ $issues = array(PhabricatorConfigStorageSchema::ISSUE_MISSING);
+ } else if ($actual && !$expect) {
+ $issues = array(PhabricatorConfigStorageSchema::ISSUE_SURPLUS);
+ } else {
+ $issues = $actual->compareTo($expect);
+ }
+
+ return $issues;
+ }
+
+
}
diff --git a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php
new file mode 100644
--- /dev/null
+++ b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php
@@ -0,0 +1,7 @@
+<?php
+
+abstract class PhabricatorConfigSchemaSpec extends Phobject {
+
+ abstract public function buildSchemata(PhabricatorConfigServerSchema $server);
+
+}
diff --git a/src/applications/config/schema/PhabricatorConfigServerSchema.php b/src/applications/config/schema/PhabricatorConfigServerSchema.php
--- a/src/applications/config/schema/PhabricatorConfigServerSchema.php
+++ b/src/applications/config/schema/PhabricatorConfigServerSchema.php
@@ -1,6 +1,7 @@
<?php
-final class PhabricatorConfigServerSchema extends Phobject {
+final class PhabricatorConfigServerSchema
+ extends PhabricatorConfigStorageSchema {
private $databases = array();
@@ -22,4 +23,19 @@
return idx($this->getDatabases(), $key);
}
+ protected function getSubschemata() {
+ return $this->getDatabases();
+ }
+
+ public function compareToSimilarSchema(
+ PhabricatorConfigStorageSchema $expect) {
+ return array();
+ }
+
+ public function newEmptyClone() {
+ $clone = clone $this;
+ $clone->databases = array();
+ return $clone;
+ }
+
}
diff --git a/src/applications/config/schema/PhabricatorConfigStorageSchema.php b/src/applications/config/schema/PhabricatorConfigStorageSchema.php
new file mode 100644
--- /dev/null
+++ b/src/applications/config/schema/PhabricatorConfigStorageSchema.php
@@ -0,0 +1,172 @@
+<?php
+
+abstract class PhabricatorConfigStorageSchema extends Phobject {
+
+ const ISSUE_MISSING = 'missing';
+ const ISSUE_SURPLUS = 'surplus';
+ const ISSUE_CHARSET = 'charset';
+ const ISSUE_COLLATION = 'collation';
+ const ISSUE_COLUMNTYPE = 'columntype';
+ const ISSUE_SUBWARN = 'subwarn';
+ const ISSUE_SUBFAIL = 'subfail';
+
+ const STATUS_OKAY = 'okay';
+ const STATUS_WARN = 'warn';
+ const STATUS_FAIL = 'fail';
+
+ private $issues = array();
+ private $name;
+
+ abstract public function newEmptyClone();
+ abstract protected function compareToSimilarSchema(
+ PhabricatorConfigStorageSchema $expect);
+ abstract protected function getSubschemata();
+
+ public function compareTo(PhabricatorConfigStorageSchema $expect) {
+ if (get_class($expect) != get_class($this)) {
+ throw new Exception(pht('Classes must match to compare schemata!'));
+ }
+
+ if ($this->getName() != $expect->getName()) {
+ throw new Exception(pht('Names must match to compare schemata!'));
+ }
+
+ return $this->compareToSimilarSchema($expect);
+ }
+
+ public function setName($name) {
+ $this->name = $name;
+ return $this;
+ }
+
+ public function getName() {
+ return $this->name;
+ }
+
+ public function setIssues(array $issues) {
+ $this->issues = array_fuse($issues);
+ return $this;
+ }
+
+ public function getIssues() {
+ $issues = $this->issues;
+
+ foreach ($this->getSubschemata() as $sub) {
+ switch ($sub->getStatus()) {
+ case self::STATUS_WARN:
+ $issues[self::ISSUE_SUBWARN] = self::ISSUE_SUBWARN;
+ break;
+ case self::STATUS_FAIL:
+ $issues[self::ISSUE_SUBFAIL] = self::ISSUE_SUBFAIL;
+ break;
+ }
+ }
+
+ return $issues;
+ }
+
+ public function hasIssue($issue) {
+ return (bool)idx($this->getIssues(), $issue);
+ }
+
+ public function getAllIssues() {
+ $issues = $this->getIssues();
+ foreach ($this->getSubschemata() as $sub) {
+ $issues += $sub->getAllIssues();
+ }
+ return $issues;
+ }
+
+ public function getStatus() {
+ $status = self::STATUS_OKAY;
+ foreach ($this->getAllIssues() as $issue) {
+ $issue_status = self::getIssueStatus($issue);
+ $status = self::getStrongestStatus($status, $issue_status);
+ }
+ return $status;
+ }
+
+ public static function getIssueName($issue) {
+ switch ($issue) {
+ case self::ISSUE_MISSING:
+ return pht('Missing');
+ case self::ISSUE_SURPLUS:
+ return pht('Surplus');
+ case self::ISSUE_CHARSET:
+ return pht('Wrong Character Set');
+ case self::ISSUE_COLLATION:
+ return pht('Wrong Collation');
+ case self::ISSUE_COLUMNTYPE:
+ return pht('Wrong Column Type');
+ case self::ISSUE_SUBWARN:
+ return pht('Subschemata Have Warnings');
+ case self::ISSUE_SUBFAIL:
+ return pht('Subschemata Have Failures');
+ default:
+ throw new Exception(pht('Unknown schema issue "%s"!', $issue));
+ }
+ }
+
+ public static function getIssueDescription($issue) {
+ switch ($issue) {
+ case self::ISSUE_MISSING:
+ return pht('This schema is expected to exist, but does not.');
+ case self::ISSUE_SURPLUS:
+ return pht('This schema is not expected to exist.');
+ case self::ISSUE_CHARSET:
+ return pht('This schema can use a better character set.');
+ case self::ISSUE_COLLATION:
+ return pht('This schema can use a better collation.');
+ case self::ISSUE_COLUMNTYPE:
+ return pht('This schema can use a better column type.');
+ case self::ISSUE_SUBWARN:
+ return pht('Subschemata have setup warnings.');
+ case self::ISSUE_SUBFAIL:
+ return pht('Subschemata have setup failures.');
+ default:
+ throw new Exception(pht('Unknown schema issue "%s"!', $issue));
+ }
+ }
+
+ public static function getIssueStatus($issue) {
+ switch ($issue) {
+ case self::ISSUE_MISSING:
+ case self::ISSUE_SUBFAIL:
+ return self::STATUS_FAIL;
+ case self::ISSUE_SURPLUS:
+ case self::ISSUE_CHARSET:
+ case self::ISSUE_COLLATION:
+ case self::ISSUE_COLUMNTYPE:
+ case self::ISSUE_SUBWARN:
+ return self::STATUS_WARN;
+ default:
+ throw new Exception(pht('Unknown schema issue "%s"!', $issue));
+ }
+ }
+
+ public static function getStatusSeverity($status) {
+ switch ($status) {
+ case self::STATUS_FAIL:
+ return 2;
+ case self::STATUS_WARN:
+ return 1;
+ case self::STATUS_OKAY:
+ return 0;
+ default:
+ throw new Exception(pht('Unknown schema status "%s"!', $status));
+ }
+ }
+
+ public static function getStrongestStatus($u, $v) {
+ $u_sev = self::getStatusSeverity($u);
+ $v_sev = self::getStatusSeverity($v);
+
+ if ($u_sev >= $v_sev) {
+ return $u;
+ } else {
+ return $v;
+ }
+ }
+
+
+}
diff --git a/src/applications/config/schema/PhabricatorConfigTableSchema.php b/src/applications/config/schema/PhabricatorConfigTableSchema.php
--- a/src/applications/config/schema/PhabricatorConfigTableSchema.php
+++ b/src/applications/config/schema/PhabricatorConfigTableSchema.php
@@ -1,8 +1,8 @@
<?php
-final class PhabricatorConfigTableSchema extends Phobject {
+final class PhabricatorConfigTableSchema
+ extends PhabricatorConfigStorageSchema {
- private $name;
private $collation;
private $columns = array();
@@ -20,6 +20,14 @@
return $this->columns;
}
+ public function getColumn($key) {
+ return idx($this->getColumns(), $key);
+ }
+
+ protected function getSubschemata() {
+ return $this->getColumns();
+ }
+
public function setCollation($collation) {
$this->collation = $collation;
return $this;
@@ -29,13 +37,21 @@
return $this->collation;
}
- public function setName($name) {
- $this->name = $name;
- return $this;
+ public function compareToSimilarSchema(
+ PhabricatorConfigStorageSchema $expect) {
+
+ $issues = array();
+ if ($this->getCollation() != $expect->getCollation()) {
+ $issues[] = self::ISSUE_COLLATION;
+ }
+
+ return $issues;
}
- public function getName() {
- return $this->name;
+ public function newEmptyClone() {
+ $clone = clone $this;
+ $clone->columns = array();
+ return $clone;
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Aug 31, 3:37 AM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
8496823
Default Alt Text
D10496.diff (30 KB)
Attached To
Mode
D10496: Generate expected and comparison schemata
Attached
Detach File
Event Timeline
Log In to Comment