[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/config/controller/ -> PhabricatorConfigDatabaseStatusController.php (source)

   1  <?php
   2  
   3  final class PhabricatorConfigDatabaseStatusController
   4    extends PhabricatorConfigDatabaseController {
   5  
   6    private $database;
   7    private $table;
   8    private $column;
   9    private $key;
  10  
  11    public function willProcessRequest(array $data) {
  12      $this->database = idx($data, 'database');
  13      $this->table = idx($data, 'table');
  14      $this->column = idx($data, 'column');
  15      $this->key = idx($data, 'key');
  16    }
  17  
  18    public function processRequest() {
  19      $request = $this->getRequest();
  20      $viewer = $request->getUser();
  21  
  22      $query = $this->buildSchemaQuery();
  23  
  24      $actual = $query->loadActualSchema();
  25      $expect = $query->loadExpectedSchema();
  26      $comp = $query->buildComparisonSchema($expect, $actual);
  27  
  28      if ($this->column) {
  29        return $this->renderColumn(
  30          $comp,
  31          $expect,
  32          $actual,
  33          $this->database,
  34          $this->table,
  35          $this->column);
  36      } else if ($this->key) {
  37        return $this->renderKey(
  38          $comp,
  39          $expect,
  40          $actual,
  41          $this->database,
  42          $this->table,
  43          $this->key);
  44      } else if ($this->table) {
  45        return $this->renderTable(
  46          $comp,
  47          $expect,
  48          $actual,
  49          $this->database,
  50          $this->table);
  51      } else if ($this->database) {
  52        return $this->renderDatabase(
  53          $comp,
  54          $expect,
  55          $actual,
  56          $this->database);
  57      } else {
  58        return $this->renderServer(
  59          $comp,
  60          $expect,
  61          $actual);
  62      }
  63    }
  64  
  65    private function buildResponse($title, $body) {
  66      $nav = $this->buildSideNavView();
  67      $nav->selectFilter('database/');
  68  
  69      $crumbs = $this->buildApplicationCrumbs();
  70      if ($this->database) {
  71        $crumbs->addTextCrumb(
  72          pht('Database Status'),
  73          $this->getApplicationURI('database/'));
  74        if ($this->table) {
  75          $crumbs->addTextCrumb(
  76            $this->database,
  77            $this->getApplicationURI('database/'.$this->database.'/'));
  78          if ($this->column || $this->key) {
  79            $crumbs->addTextCrumb(
  80              $this->table,
  81              $this->getApplicationURI(
  82                'database/'.$this->database.'/'.$this->table.'/'));
  83            if ($this->column) {
  84              $crumbs->addTextCrumb($this->column);
  85            } else {
  86              $crumbs->addTextCrumb($this->key);
  87            }
  88          } else {
  89            $crumbs->addTextCrumb($this->table);
  90          }
  91        } else {
  92          $crumbs->addTextCrumb($this->database);
  93        }
  94      } else {
  95        $crumbs->addTextCrumb(pht('Database Status'));
  96      }
  97  
  98      $nav->setCrumbs($crumbs);
  99      $nav->appendChild($body);
 100  
 101      return $this->buildApplicationPage(
 102        $nav,
 103        array(
 104          'title' => $title,
 105        ));
 106    }
 107  
 108  
 109    private function renderServer(
 110      PhabricatorConfigServerSchema $comp,
 111      PhabricatorConfigServerSchema $expect,
 112      PhabricatorConfigServerSchema $actual) {
 113  
 114      $charset_issue = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
 115      $collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
 116  
 117      $rows = array();
 118      foreach ($comp->getDatabases() as $database_name => $database) {
 119        $actual_database = $actual->getDatabase($database_name);
 120        if ($actual_database) {
 121          $charset = $actual_database->getCharacterSet();
 122          $collation = $actual_database->getCollation();
 123        } else {
 124          $charset = null;
 125          $collation = null;
 126        }
 127  
 128        $status = $database->getStatus();
 129        $issues = $database->getIssues();
 130  
 131        $rows[] = array(
 132          $this->renderIcon($status),
 133          phutil_tag(
 134            'a',
 135            array(
 136              'href' => $this->getApplicationURI(
 137                '/database/'.$database_name.'/'),
 138            ),
 139            $database_name),
 140          $this->renderAttr($charset, $database->hasIssue($charset_issue)),
 141          $this->renderAttr($collation, $database->hasIssue($collation_issue)),
 142        );
 143      }
 144  
 145      $table = id(new AphrontTableView($rows))
 146        ->setHeaders(
 147          array(
 148            null,
 149            pht('Database'),
 150            pht('Charset'),
 151            pht('Collation'),
 152          ))
 153        ->setColumnClasses(
 154          array(
 155            null,
 156            'wide pri',
 157            null,
 158            null,
 159          ));
 160  
 161      $title = pht('Database Status');
 162  
 163      $properties = $this->buildProperties(
 164        array(
 165        ),
 166        $comp->getIssues());
 167  
 168      $box = id(new PHUIObjectBoxView())
 169        ->setHeader($this->buildHeaderWithDocumentationLink($title))
 170        ->addPropertyList($properties)
 171        ->appendChild($table);
 172  
 173      return $this->buildResponse($title, $box);
 174    }
 175  
 176    private function renderDatabase(
 177      PhabricatorConfigServerSchema $comp,
 178      PhabricatorConfigServerSchema $expect,
 179      PhabricatorConfigServerSchema $actual,
 180      $database_name) {
 181  
 182      $collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
 183  
 184      $database = $comp->getDatabase($database_name);
 185      if (!$database) {
 186        return new Aphront404Response();
 187      }
 188  
 189      $rows = array();
 190      foreach ($database->getTables() as $table_name => $table) {
 191        $status = $table->getStatus();
 192  
 193        $rows[] = array(
 194          $this->renderIcon($status),
 195          phutil_tag(
 196            'a',
 197            array(
 198              'href' => $this->getApplicationURI(
 199                '/database/'.$database_name.'/'.$table_name.'/'),
 200            ),
 201            $table_name),
 202          $this->renderAttr(
 203            $table->getCollation(),
 204            $table->hasIssue($collation_issue)),
 205        );
 206      }
 207  
 208      $table = id(new AphrontTableView($rows))
 209        ->setHeaders(
 210          array(
 211            null,
 212            pht('Table'),
 213            pht('Collation'),
 214          ))
 215        ->setColumnClasses(
 216          array(
 217            null,
 218            'wide pri',
 219            null,
 220          ));
 221  
 222      $title = pht('Database Status: %s', $database_name);
 223  
 224      $actual_database = $actual->getDatabase($database_name);
 225      if ($actual_database) {
 226        $actual_charset = $actual_database->getCharacterSet();
 227        $actual_collation = $actual_database->getCollation();
 228      } else {
 229        $actual_charset = null;
 230        $actual_collation = null;
 231      }
 232  
 233      $expect_database = $expect->getDatabase($database_name);
 234      if ($expect_database) {
 235        $expect_charset = $expect_database->getCharacterSet();
 236        $expect_collation = $expect_database->getCollation();
 237      } else {
 238        $expect_charset = null;
 239        $expect_collation = null;
 240      }
 241  
 242      $properties = $this->buildProperties(
 243        array(
 244          array(
 245            pht('Character Set'),
 246            $actual_charset,
 247          ),
 248          array(
 249            pht('Expected Character Set'),
 250            $expect_charset,
 251          ),
 252          array(
 253            pht('Collation'),
 254            $actual_collation,
 255          ),
 256          array(
 257            pht('Expected Collation'),
 258            $expect_collation,
 259          ),
 260        ),
 261        $database->getIssues());
 262  
 263      $box = id(new PHUIObjectBoxView())
 264        ->setHeader($this->buildHeaderWithDocumentationLink($title))
 265        ->addPropertyList($properties)
 266        ->appendChild($table);
 267  
 268      return $this->buildResponse($title, $box);
 269    }
 270  
 271    private function renderTable(
 272      PhabricatorConfigServerSchema $comp,
 273      PhabricatorConfigServerSchema $expect,
 274      PhabricatorConfigServerSchema $actual,
 275      $database_name,
 276      $table_name) {
 277  
 278      $type_issue = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE;
 279      $charset_issue = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
 280      $collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
 281      $nullable_issue = PhabricatorConfigStorageSchema::ISSUE_NULLABLE;
 282      $unique_issue = PhabricatorConfigStorageSchema::ISSUE_UNIQUE;
 283      $columns_issue = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS;
 284      $longkey_issue = PhabricatorConfigStorageSchema::ISSUE_LONGKEY;
 285      $auto_issue = PhabricatorConfigStorageSchema::ISSUE_AUTOINCREMENT;
 286  
 287      $database = $comp->getDatabase($database_name);
 288      if (!$database) {
 289        return new Aphront404Response();
 290      }
 291  
 292      $table = $database->getTable($table_name);
 293      if (!$table) {
 294        return new Aphront404Response();
 295      }
 296  
 297      $actual_database = $actual->getDatabase($database_name);
 298      $actual_table = null;
 299      if ($actual_database) {
 300        $actual_table = $actual_database->getTable($table_name);
 301      }
 302  
 303      $expect_database = $expect->getDatabase($database_name);
 304      $expect_table = null;
 305      if ($expect_database) {
 306        $expect_table = $expect_database->getTable($table_name);
 307      }
 308  
 309      $rows = array();
 310      foreach ($table->getColumns() as $column_name => $column) {
 311        $expect_column = null;
 312        if ($expect_table) {
 313          $expect_column = $expect_table->getColumn($column_name);
 314        }
 315  
 316        $status = $column->getStatus();
 317  
 318        $data_type = null;
 319        if ($expect_column) {
 320          $data_type = $expect_column->getDataType();
 321        }
 322  
 323        $rows[] = array(
 324          $this->renderIcon($status),
 325          phutil_tag(
 326            'a',
 327            array(
 328              'href' => $this->getApplicationURI(
 329                'database/'.
 330                $database_name.'/'.
 331                $table_name.'/'.
 332                'col/'.
 333                $column_name.'/'),
 334            ),
 335            $column_name),
 336          $data_type,
 337          $this->renderAttr(
 338            $column->getColumnType(),
 339            $column->hasIssue($type_issue)),
 340          $this->renderAttr(
 341            $this->renderBoolean($column->getNullable()),
 342            $column->hasIssue($nullable_issue)),
 343          $this->renderAttr(
 344            $this->renderBoolean($column->getAutoIncrement()),
 345            $column->hasIssue($auto_issue)),
 346          $this->renderAttr(
 347            $column->getCharacterSet(),
 348            $column->hasIssue($charset_issue)),
 349          $this->renderAttr(
 350            $column->getCollation(),
 351            $column->hasIssue($collation_issue)),
 352        );
 353      }
 354  
 355      $table_view = id(new AphrontTableView($rows))
 356        ->setHeaders(
 357          array(
 358            null,
 359            pht('Column'),
 360            pht('Data Type'),
 361            pht('Column Type'),
 362            pht('Nullable'),
 363            pht('Autoincrement'),
 364            pht('Character Set'),
 365            pht('Collation'),
 366          ))
 367        ->setColumnClasses(
 368          array(
 369            null,
 370            'wide pri',
 371            null,
 372            null,
 373            null,
 374            null,
 375            null,
 376          ));
 377  
 378      $key_rows = array();
 379      foreach ($table->getKeys() as $key_name => $key) {
 380        $expect_key = null;
 381        if ($expect_table) {
 382          $expect_key = $expect_table->getKey($key_name);
 383        }
 384  
 385        $status = $key->getStatus();
 386  
 387        $size = 0;
 388        foreach ($key->getColumnNames() as $column_spec) {
 389          list($column_name, $prefix) = $key->getKeyColumnAndPrefix($column_spec);
 390          $column = $table->getColumn($column_name);
 391          if (!$column) {
 392            $size = 0;
 393            break;
 394          }
 395          $size += $column->getKeyByteLength($prefix);
 396        }
 397  
 398        $size_formatted = null;
 399        if ($size) {
 400          $size_formatted = $this->renderAttr(
 401            $size,
 402            $key->hasIssue($longkey_issue));
 403        }
 404  
 405        $key_rows[] = array(
 406          $this->renderIcon($status),
 407          phutil_tag(
 408            'a',
 409            array(
 410              'href' => $this->getApplicationURI(
 411                'database/'.
 412                $database_name.'/'.
 413                $table_name.'/'.
 414                'key/'.
 415                $key_name.'/'),
 416            ),
 417            $key_name),
 418          $this->renderAttr(
 419            implode(', ', $key->getColumnNames()),
 420            $key->hasIssue($columns_issue)),
 421          $this->renderAttr(
 422            $this->renderBoolean($key->getUnique()),
 423            $key->hasIssue($unique_issue)),
 424          $size_formatted,
 425        );
 426      }
 427  
 428      $keys_view = id(new AphrontTableView($key_rows))
 429        ->setHeaders(
 430          array(
 431            null,
 432            pht('Key'),
 433            pht('Columns'),
 434            pht('Unique'),
 435            pht('Size'),
 436          ))
 437        ->setColumnClasses(
 438          array(
 439            null,
 440            'wide pri',
 441            null,
 442            null,
 443            null,
 444          ));
 445  
 446      $title = pht('Database Status: %s.%s', $database_name, $table_name);
 447  
 448      if ($actual_table) {
 449        $actual_collation = $actual_table->getCollation();
 450      } else {
 451        $actual_collation = null;
 452      }
 453  
 454      if ($expect_table) {
 455        $expect_collation = $expect_table->getCollation();
 456      } else {
 457        $expect_collation = null;
 458      }
 459  
 460      $properties = $this->buildProperties(
 461        array(
 462          array(
 463            pht('Collation'),
 464            $actual_collation,
 465          ),
 466          array(
 467            pht('Expected Collation'),
 468            $expect_collation,
 469          ),
 470        ),
 471        $table->getIssues());
 472  
 473      $box = id(new PHUIObjectBoxView())
 474        ->setHeader($this->buildHeaderWithDocumentationLink($title))
 475        ->addPropertyList($properties)
 476        ->appendChild($table_view)
 477        ->appendChild($keys_view);
 478  
 479      return $this->buildResponse($title, $box);
 480    }
 481  
 482    private function renderColumn(
 483      PhabricatorConfigServerSchema $comp,
 484      PhabricatorConfigServerSchema $expect,
 485      PhabricatorConfigServerSchema $actual,
 486      $database_name,
 487      $table_name,
 488      $column_name) {
 489  
 490      $database = $comp->getDatabase($database_name);
 491      if (!$database) {
 492        return new Aphront404Response();
 493      }
 494  
 495      $table = $database->getTable($table_name);
 496      if (!$table) {
 497        return new Aphront404Response();
 498      }
 499  
 500      $column = $table->getColumn($column_name);
 501      if (!$column) {
 502        return new Aphront404Response();
 503      }
 504  
 505      $actual_database = $actual->getDatabase($database_name);
 506      $actual_table = null;
 507      $actual_column = null;
 508      if ($actual_database) {
 509        $actual_table = $actual_database->getTable($table_name);
 510        if ($actual_table) {
 511          $actual_column = $actual_table->getColumn($column_name);
 512        }
 513      }
 514  
 515      $expect_database = $expect->getDatabase($database_name);
 516      $expect_table = null;
 517      $expect_column = null;
 518      if ($expect_database) {
 519        $expect_table = $expect_database->getTable($table_name);
 520        if ($expect_table) {
 521          $expect_column = $expect_table->getColumn($column_name);
 522        }
 523      }
 524  
 525      if ($actual_column) {
 526        $actual_coltype = $actual_column->getColumnType();
 527        $actual_charset = $actual_column->getCharacterSet();
 528        $actual_collation = $actual_column->getCollation();
 529        $actual_nullable = $actual_column->getNullable();
 530        $actual_auto = $actual_column->getAutoIncrement();
 531      } else {
 532        $actual_coltype = null;
 533        $actual_charset = null;
 534        $actual_collation = null;
 535        $actual_nullable = null;
 536        $actual_auto = null;
 537      }
 538  
 539      if ($expect_column) {
 540        $data_type = $expect_column->getDataType();
 541        $expect_coltype = $expect_column->getColumnType();
 542        $expect_charset = $expect_column->getCharacterSet();
 543        $expect_collation = $expect_column->getCollation();
 544        $expect_nullable = $expect_column->getNullable();
 545        $expect_auto = $expect_column->getAutoIncrement();
 546      } else {
 547        $data_type = null;
 548        $expect_coltype = null;
 549        $expect_charset = null;
 550        $expect_collation = null;
 551        $expect_nullable = null;
 552        $expect_auto = null;
 553      }
 554  
 555  
 556      $title = pht(
 557        'Database Status: %s.%s.%s',
 558        $database_name,
 559        $table_name,
 560        $column_name);
 561  
 562      $properties = $this->buildProperties(
 563        array(
 564          array(
 565            pht('Data Type'),
 566            $data_type,
 567          ),
 568          array(
 569            pht('Column Type'),
 570            $actual_coltype,
 571          ),
 572          array(
 573            pht('Expected Column Type'),
 574            $expect_coltype,
 575          ),
 576          array(
 577            pht('Character Set'),
 578            $actual_charset,
 579          ),
 580          array(
 581            pht('Expected Character Set'),
 582            $expect_charset,
 583          ),
 584          array(
 585            pht('Collation'),
 586            $actual_collation,
 587          ),
 588          array(
 589            pht('Expected Collation'),
 590            $expect_collation,
 591          ),
 592          array(
 593            pht('Nullable'),
 594            $this->renderBoolean($actual_nullable),
 595          ),
 596          array(
 597            pht('Expected Nullable'),
 598            $this->renderBoolean($expect_nullable),
 599          ),
 600          array(
 601            pht('Autoincrement'),
 602            $this->renderBoolean($actual_auto),
 603          ),
 604          array(
 605            pht('Expected Autoincrement'),
 606            $this->renderBoolean($expect_auto),
 607          ),
 608        ),
 609        $column->getIssues());
 610  
 611      $box = id(new PHUIObjectBoxView())
 612        ->setHeader($this->buildHeaderWithDocumentationLink($title))
 613        ->addPropertyList($properties);
 614  
 615      return $this->buildResponse($title, $box);
 616    }
 617  
 618    private function renderKey(
 619      PhabricatorConfigServerSchema $comp,
 620      PhabricatorConfigServerSchema $expect,
 621      PhabricatorConfigServerSchema $actual,
 622      $database_name,
 623      $table_name,
 624      $key_name) {
 625  
 626      $database = $comp->getDatabase($database_name);
 627      if (!$database) {
 628        return new Aphront404Response();
 629      }
 630  
 631      $table = $database->getTable($table_name);
 632      if (!$table) {
 633        return new Aphront404Response();
 634      }
 635  
 636      $key = $table->getKey($key_name);
 637      if (!$key) {
 638        return new Aphront404Response();
 639      }
 640  
 641      $actual_database = $actual->getDatabase($database_name);
 642      $actual_table = null;
 643      $actual_key = null;
 644      if ($actual_database) {
 645        $actual_table = $actual_database->getTable($table_name);
 646        if ($actual_table) {
 647          $actual_key = $actual_table->getKey($key_name);
 648        }
 649      }
 650  
 651      $expect_database = $expect->getDatabase($database_name);
 652      $expect_table = null;
 653      $expect_key = null;
 654      if ($expect_database) {
 655        $expect_table = $expect_database->getTable($table_name);
 656        if ($expect_table) {
 657          $expect_key = $expect_table->getKey($key_name);
 658        }
 659      }
 660  
 661      if ($actual_key) {
 662        $actual_columns = $actual_key->getColumnNames();
 663        $actual_unique = $actual_key->getUnique();
 664      } else {
 665        $actual_columns = array();
 666        $actual_unique = null;
 667      }
 668  
 669      if ($expect_key) {
 670        $expect_columns = $expect_key->getColumnNames();
 671        $expect_unique = $expect_key->getUnique();
 672      } else {
 673        $expect_columns = array();
 674        $expect_unique = null;
 675      }
 676  
 677      $title = pht(
 678        'Database Status: %s.%s (%s)',
 679        $database_name,
 680        $table_name,
 681        $key_name);
 682  
 683      $properties = $this->buildProperties(
 684        array(
 685          array(
 686            pht('Unique'),
 687            $this->renderBoolean($actual_unique),
 688          ),
 689          array(
 690            pht('Expected Unique'),
 691            $this->renderBoolean($expect_unique),
 692          ),
 693          array(
 694            pht('Columns'),
 695            implode(', ', $actual_columns),
 696          ),
 697          array(
 698            pht('Expected Columns'),
 699            implode(', ', $expect_columns),
 700          ),
 701        ),
 702        $key->getIssues());
 703  
 704      $box = id(new PHUIObjectBoxView())
 705        ->setHeader($this->buildHeaderWithDocumentationLink($title))
 706        ->addPropertyList($properties);
 707  
 708      return $this->buildResponse($title, $box);
 709    }
 710  
 711    private function buildProperties(array $properties, array $issues) {
 712      $view = id(new PHUIPropertyListView())
 713        ->setUser($this->getRequest()->getUser());
 714  
 715      foreach ($properties as $property) {
 716        list($key, $value) = $property;
 717        $view->addProperty($key, $value);
 718      }
 719  
 720      $status_view = new PHUIStatusListView();
 721      if (!$issues) {
 722        $status_view->addItem(
 723          id(new PHUIStatusItemView())
 724            ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
 725            ->setTarget(pht('No Schema Issues')));
 726      } else {
 727        foreach ($issues as $issue) {
 728          $note = PhabricatorConfigStorageSchema::getIssueDescription($issue);
 729  
 730          $status = PhabricatorConfigStorageSchema::getIssueStatus($issue);
 731          switch ($status) {
 732            case PhabricatorConfigStorageSchema::STATUS_WARN:
 733              $icon = PHUIStatusItemView::ICON_WARNING;
 734              $color = 'yellow';
 735              break;
 736            case PhabricatorConfigStorageSchema::STATUS_FAIL:
 737            default:
 738              $icon = PHUIStatusItemView::ICON_REJECT;
 739              $color = 'red';
 740              break;
 741          }
 742  
 743          $item = id(new PHUIStatusItemView())
 744            ->setTarget(PhabricatorConfigStorageSchema::getIssueName($issue))
 745            ->setIcon($icon, $color)
 746            ->setNote($note);
 747  
 748          $status_view->addItem($item);
 749        }
 750      }
 751      $view->addProperty(pht('Schema Status'), $status_view);
 752  
 753      return $view;
 754    }
 755  
 756  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1