Skip to content

Commit

Permalink
Merge pull request #17 from statonlab/add-db-checks
Browse files Browse the repository at this point in the history
Add db checks
  • Loading branch information
almasaeed2010 committed Aug 25, 2017
2 parents 16ebfbe + c21d97e commit bf0da48
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 16 deletions.
86 changes: 78 additions & 8 deletions src/CLIPrompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class CLIPrompt {
/**
* CLIPrompt constructor.
*
* @param $file string [optional] Input file path.
* @param string $file [optional] Input file path.
*
* @return void
*/
Expand All @@ -38,18 +38,88 @@ public function __construct($file = 'php://stdin') {
/**
* Prompts the user for an answer to the provided question.
*
* @param $question string Question to prompt the user.
* @param string $question Question to prompt the user.
*
* @return string
*/
public function ask($question) {
while (empty($response = readline($question))) {
public function ask($question, $style = NULL) {
if ($style) {
$question = $this->applyStyle($question, $style);
}

echo $question;
while (empty($response = readline())) {
$this->error('Please provide a response');
echo $question;
}

return $response;
}

protected function applyStyle($str, $style) {
switch ($style) {
case 'warning':
$str = $this->colored->str($str, 'yellow');
break;
case 'danger':
case 'error':
$str = $this->colored->str($str, 'red');
break;
case 'info':
$str = $this->colored->str($str, 'blue');
break;
}

return $str;
}

/**
* Ask a yes or no question.
*
* @param string $question the question.
*
* @return bool
*/
public function askBool($question, $style = NULL) {
$answer = strtolower($this->ask($question . ' [Y/n]:', $style));
while (!in_array($answer, ['y', 'n', 'yes', 'no'])) {
$this->error('Please answer with "yes", "no", "y" or "n"');
}

if (substr($answer, 0, 1) === 'y') {
return TRUE;
}

return FALSE;
}

/**
* Ask multiple choice questions.
*
* @param string $question The question.
* @param array $options A list of options.
*
* @return int The index of the selected option.
*/
public function askMultipleChoice($question, $options, $style = NULL) {
if($style) {
$question = $this->applyStyle($question, $style);
}

$this->line($question);
$len = count($options);

for ($i = 1; $i <= $len; $i++) {
$this->line("[$i] {$options[$i - 1]}");
}

do {
$answer = $this->ask('Please enter an option number: ');
} while ($answer < 1 || $answer > $len);

return intval($answer) - 1;
}

/**
* Prints a line to the file.
*
Expand All @@ -62,7 +132,7 @@ public function line($message) {
/**
* Prints a line with a blue background.
*
* @param $message
* @param string $message
*/
public function info($message) {
echo $this->colored->str($message, 'blue') . PHP_EOL;
Expand All @@ -71,7 +141,7 @@ public function info($message) {
/**
* Prints a line with a red background.
*
* @param $message
* @param string $message
*/
public function error($message) {
echo $this->colored->str($message, 'red') . PHP_EOL;
Expand All @@ -80,7 +150,7 @@ public function error($message) {
/**
* Prints a line with yellow background.
*
* @param $message
* @param string $message
*/
public function warn($message) {
echo $this->colored->str($message, 'yellow') . PHP_EOL;
Expand All @@ -89,7 +159,7 @@ public function warn($message) {
/**
* Prints a line with a green background.
*
* @param $message
* @param string $message
*/
public function success($message) {
echo $this->colored->str($message, 'black', 'green') . PHP_EOL;
Expand Down
8 changes: 4 additions & 4 deletions src/Colors.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function __construct() {
public function str($string, $foreground_color = NULL, $background_color = NULL) {
$colored_string = '';
$colored_padding = '';
$string = ' ' . $string . ' ';
//$string = ' ' . $string . ' ';
$padding = str_pad('', strlen($string), ' ');;

// Check if given foreground color found
Expand All @@ -77,9 +77,9 @@ public function str($string, $foreground_color = NULL, $background_color = NULL)
// Add string and end coloring
$colored_string .= $string . "\033[0m";

$full_string = ' ' . $colored_padding . PHP_EOL;
$full_string .= ' ' . $colored_string . PHP_EOL;
$full_string .= ' ' . $colored_padding;
//$full_string = $colored_padding . PHP_EOL;
$full_string = $colored_string;// . PHP_EOL;
//$full_string .= $colored_padding;
}
else {
$full_string = $colored_string;
Expand Down
14 changes: 12 additions & 2 deletions src/DB.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class DB {

/**
* P
*
* @var array
*/
protected $parameters;
Expand Down Expand Up @@ -134,11 +135,20 @@ public function query($sql, $parameters = []) {
public function get() {
$execute = $this->prepared->execute($this->parameters);

if(!$execute) {
if (!$execute) {
$error = $this->prepared->errorInfo();
throw new Exception("Couldn't execute query. $this->sql. " . $error[2]);
throw new Exception("Couldn't execute query. $this->sql. " . PHP_EOL . implode(' ', $error));
}

return $this->prepared->fetchAll();
}

/**
* Get the count directly.
*
* @return mixed
*/
public function count() {
return intval($this->get()[0]['count']);
}
}
149 changes: 147 additions & 2 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ class Generator {
*/
protected $options;

/**
* Database connection.
*
* @var null|\StatonLab\FieldGenerator\DB
*/
protected $db = NULL;

/**
Expand Down Expand Up @@ -140,7 +145,7 @@ public function run() {
$this->printIntro();

foreach ($this->questions as $question => $field) {
$this->{$field} = $this->prompt->ask($question);
$this->{$field} = trim($this->prompt->ask($question));
}

// Auto construct field name
Expand All @@ -151,7 +156,7 @@ public function run() {

$files = $this->generate();

// TODO: CHECK TERMS AGAINST DB HERE
$this->validateTerms();

try {
return $this->make($files);
Expand All @@ -174,6 +179,146 @@ protected function validateOptions() {
}
}

/**
* Validate provided terms in DB.
*/
protected function validateTerms() {
$this->prompt->info('Performing DB checks to validate entries ...');
$failed = FALSE;

// Validate DB
$count = $this->count('chado.db', 'name', $this->db_name);
if ($count <= 0) {
$failed = TRUE;
$answer = $this->prompt->askBool("The DB \"{$this->db_name}\" does not exist in the chado.db table. Using this value will create a new DB. Are you sure?");
if (!$answer) {
$this->terminate();
}
}

// Validate CV
$count = $this->count('chado.cv', 'name', $this->cv_name);
if ($count <= 0) {
$failed = TRUE;
$answer = $this->prompt->askBool("The CV \"{$this->cv_name}\" does not exist in the chado.cv table. Using this value will create a new CV. Are you sure?");
if (!$answer) {
$this->terminate();
}
}

// Validate CV Term
$count = $this->count('chado.cvterm', 'name', $this->cv_term);
if ($count <= 0) {
$failed = TRUE;
$answer = $this->prompt->askBool("The CV term \"{$this->cv_term}\" does not exist in the chado.cvterm table. Using this value will create a new CV. Are you sure?");
if (!$answer) {
$this->terminate();
}
}

if (!$failed) {
$results = $this->db->query('SELECT CV.name AS cv_name, DB.name AS db_name, DBX.accession AS accession
FROM chado.cvterm AS CVTERM
JOIN chado.cv AS CV ON CVTERM.cv_id = CV.cv_id
JOIN chado.dbxref AS DBX ON CVTERM.dbxref_id = DBX.dbxref_id
JOIN chado.db AS DB ON DBX.db_id = DB.db_id
WHERE CVTERM.name = :cv_term', [':cv_term' => $this->cv_term])
->get();
$count = count($results);
switch ($count) {
case 0:
$this->prompt->askBool('Warning: the CV, DB, and CVterm are not properly linked through the chado.dbxref table. If this term was manually inserted into the db, remove it before adding the new term.', 'warning');
break;
case 1:
$this->verifyAccession($results[0]);
break;
default:
$this->handleMultiDBXRef($results);
break;
}
}

$this->prompt->info("Chosen CV Term ID {$this->db_name}:{$this->field_accession} and CV {$this->cv_name}");
$this->prompt->info('DB checks succeeded');
}

/**
* Verify that the entered accession is equivalent to the one in the DB.
*
* @param array $result
*/
protected function verifyAccession($result) {
if (!$this->checkAccessionInDB($result)) {
$answer = $this->prompt->askBool("The accession in chado is {$result['accession']}, which does not match the provided the accession ({$this->field_accession}). Would you like to use {$result['accession']} instead?", 'warning');
if ($answer) {
$this->field_accession = $result['accession'];
}
}
}

/**
* Handle multiple results from DB.
*
* @param array $results 2d array of db results.
*/
protected function handleMultiDBXRef($results) {
// Create options array.
$options = [];
$len = count($results);
foreach ($results as $result) {
$options[] = "ID {$result['db_name']}:{$results['accesion']} and controlled vocabulary {$results['cv_name']}";
}
$options[] = "None of the above. I'd like to keep my settings.";

$index = $this->prompt->askMultipleChoice('Multiple links were found to the same CV term. Please select the most accurate CV term from the list below.', $options, 'warning');

if ($index === $len) {
return;
}

$selected = $results[$index];

$this->field_accession = $selected['accession'];
$this->db_name = $selected['db_name'];
$this->cv_name = $selected['cv_name'];
}

/**
* Checks the accession validity against the DB result.
*
* @param array $result A single DB result.
*
* @return bool
*/
protected function checkAccessionInDB($result) {
// Wrapped in quotes to make sure both are evaluated as strings
return "$this->field_accession" === trim("{$result['accession']}");
}

/**
* Get the total count to a query.
*
* @param $table
* @param $condition_column
* @param $condition_value
*
* @return mixed
*/
protected function count($table, $condition_column, $condition_value) {
$sql = "SELECT COUNT(*) AS count FROM $table AS DB WHERE DB.{$condition_column} = :condition_column";
return $this->db->query($sql, [':condition_column' => $condition_value])
->count();
}

/**
* Terminate the generator.
*
* @throws \Exception
*/
protected function terminate() {
throw new Exception('User Terminated.');
}

/**
* Prints introduction message.
*/
Expand Down

0 comments on commit bf0da48

Please sign in to comment.