Skip to content

Commit

Permalink
Improve CI and add translations
Browse files Browse the repository at this point in the history
  • Loading branch information
filisko committed Mar 8, 2020
1 parent 543256c commit 0dc626c
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 97 deletions.
2 changes: 1 addition & 1 deletion ci/check_filters_docs.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
print(sprintf('⮕ %s', $error).PHP_EOL);
}

print(PHP_EOL.'Run "php ci/dump_filters_docs.php" to fix this!');
print(PHP_EOL.'Run "php ci/dump_filters_docs.php" to fix this!'.PHP_EOL);
exit(1);
} else {
print('Docs checks successfully passed for filters!'.PHP_EOL);
Expand Down
2 changes: 1 addition & 1 deletion ci/check_validators_docs.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
print(sprintf('⮕ %s', $error).PHP_EOL);
}

print(PHP_EOL.'Run "php ci/dump_validators_docs.php" to fix this!');
print(PHP_EOL.'Run "php ci/dump_validators_docs.php" to fix this!'.PHP_EOL);
exit(1);
} else {
print('Docs checks successfully passed for validators!'.PHP_EOL);
Expand Down
21 changes: 21 additions & 0 deletions ci/check_validators_translations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php
require_once 'ci/boot.php';

$validators = array_keys(get_gump_validators());
$translations = array_map(function($item) {
return str_replace('validate_', '', $item);
}, array_keys(require 'lang/en.php'));


$missingTranslations = array_diff($validators, $translations);

if (count($missingTranslations) > 0) {
foreach ($missingTranslations as $missingTranslation) {
print(sprintf('⮕ %s error message is missing!', $missingTranslation).PHP_EOL);
}

print(PHP_EOL.'Please add missing translations to lang/en.php file.'.PHP_EOL);
exit(1);
} else {
print('Translation checks successfully passed!'.PHP_EOL);
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
},
"scripts": {
"test": "php ./vendor/bin/phpunit",
"docs": "php ./ci/dump_filters_docs.php && php ./ci/dump_validators_docs.php"
"dump": "php ./ci/dump_filters_docs.php && php ./ci/dump_validators_docs.php",
"check": "php ./ci/check_filters_docs.php && php ./ci/check_validators_docs.php && php ./ci/check_validators_translations.php"
},
"config": {
"platform": {"php": "7.0"}
Expand Down
125 changes: 57 additions & 68 deletions gump.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ public function __construct(string $lang = 'en')
/**
* Shorthand method for inline validation.
*
* @param array $data The data to be validated
* @param array $data The data to be validated
* @param array $validators The GUMP validators
*
* @return mixed True(boolean) or the array of error messages
* @throws Exception If validation rule does not exist
*/
public static function is_valid(array $data, array $validators)
{
Expand All @@ -111,8 +111,8 @@ public static function is_valid(array $data, array $validators)
*
* @param array $data
* @param array $filters
*
* @return mixed
* @throws Exception If filter does not exist
*/
public static function filter_input(array $data, array $filters)
{
Expand Down Expand Up @@ -393,13 +393,13 @@ public function validate(array $input, array $ruleset, string $rules_delimiter='

foreach ($rules as $rule) {
if (is_null($require_rule_found) && self::is_empty($input[$field])) continue;
if (!$this->field_doesnt_have_errors($field, $this->errors)) continue;

$parsed_rule = $this->parse_rule($rule, $parameters_delimiter);
$result = $this->call_rule($parsed_rule['rule'], $field, $input, $parsed_rule['param']);

if (is_array($result)) {
$this->errors[] = $result;
break; // exit on first error
}
}
}
Expand Down Expand Up @@ -504,11 +504,6 @@ private function find_required_rule(array $rules)
return count($found) > 0 ? $found[0] : null;
}

private function field_doesnt_have_errors(string $field, array $errors)
{
return array_search($field, array_column($errors, 'field')) === false;
}

private static function validator_to_method(string $rule)
{
return sprintf('validate_%s', $rule);
Expand Down Expand Up @@ -644,63 +639,47 @@ protected function get_messages()
* @param bool $convert_to_string = false
* @param string $field_class
* @param string $error_class
*
* @return array
* @return string
* @throws Exception when validator doesn't have a set error message
* @return array|string
* @throws Exception if validator doesn't have an error message to set
*/
public function get_readable_errors(bool $convert_to_string = false, string $field_class = 'gump-field', string $error_class = 'gump-error-message')
{
if (empty($this->errors)) {
return ($convert_to_string) ? null : [];
}

$resp = [];

// Error messages
$messages = $this->get_messages();
$result = [];

foreach ($this->errors as $e) {
$field = ucwords(str_replace($this->fieldCharsToRemove, chr(32), $e['field']));
$param = $e['param'];

// Let's fetch explicitly if the field names exist
if (array_key_exists($e['field'], self::$fields)) {
$field = self::$fields[$e['field']];

// If param is a field (i.e. equalsfield validator)
if (array_key_exists($param, self::$fields)) {
$param = self::$fields[$e['param']];
}
if (!isset($messages[$e['rule']])) {
throw new Exception('Rule "'.$e['rule'].'" does not have an error message');
}

// Messages
if (isset($messages[$e['rule']])) {
if (is_array($param)) {
$param = implode(', ', $param);
$result[] = $this->process_error_message(
$e['field'], $e['param'], $messages[$e['rule']],

function($replace) use($field_class) {
$replace['{field}'] = sprintf('<span class="%s">%s</span>', $field_class, $replace['{field}']);
return $replace;
}
$message = str_replace('{param}', $param, str_replace('{field}', '<span class="'.$field_class.'">'.$field.'</span>', $messages[$e['rule']]));
$resp[] = $message;
} else {
throw new Exception('Rule "'.$e['rule'].'" does not have an error message');
}
);
}

if (!$convert_to_string) {
return $resp;
if ($convert_to_string) {
return array_reduce($result, function($prev, $next) use($error_class) {
return sprintf('%s<span class="%s">%s</span>', $prev, $error_class, $next);
});
}

return array_reduce($resp, function($prev, $next) use($error_class) {
return sprintf('%s<span class="%s">%s</span>', $prev, $error_class, $next);
});
return $result;
}

/**
* Process the validation errors and return an array of errors with field names as keys.
*
* @param $convert_to_string
*
* @return array | null (if empty)
* @param bool $convert_to_string
* @return array
* @throws Exception
*/
public function get_errors_array(bool $convert_to_string = false)
Expand All @@ -709,40 +688,50 @@ public function get_errors_array(bool $convert_to_string = false)
return ($convert_to_string) ? null : [];
}

$resp = [];

// Error messages
$messages = $this->get_messages();
$result = [];

foreach ($this->errors as $e) {
$field = ucwords(str_replace(array('_', '-'), chr(32), $e['field']));
$param = $e['param'];

// Let's fetch explicitly if the field names exist
if (array_key_exists($e['field'], self::$fields)) {
$field = self::$fields[$e['field']];

// If param is a field (i.e. equalsfield validator)
if (array_key_exists($param, self::$fields)) {
$param = self::$fields[$e['param']];
}
}

if (!isset($messages[$e['rule']])) {
throw new Exception('Rule "'.$e['rule'].'" does not have an error message');
}

// show first validation error
if (!isset($resp[$e['field']])) {
if (is_array($param)) {
$param = implode(', ', $param);
}
$message = str_replace('{param}', $param, str_replace('{field}', $field, $messages[$e['rule']]));
$resp[$e['field']] = $message;
$result[$e['field']] = $this->process_error_message($e['field'], $e['param'], $messages[$e['rule']]);
}

return $result;
}

private function process_error_message($field, $param, string $message, callable $transformer = null)
{
// if field name is explicitly set, use it
if (array_key_exists($field, self::$fields)) {
$field = self::$fields[$field];
} else {
$field = ucwords(str_replace($this->fieldCharsToRemove, chr(32), $field));
}

// if param is a field (i.e. equalsfield validator)
if (!is_array($param) && array_key_exists($param, self::$fields)) {
$param = self::$fields[$param];
}

$replace = [
'{field}' => $field,
'{param}' => $param,
];

if (is_array($param)) {
$replace['{param}'] = implode(', ', $param);
foreach ($param as $key => $value) {
$replace[sprintf('{param[%s]}', $key)] = $value;
}
}

return $resp;
// for get_readable_errors() <span>
if ($transformer) $replace = $transformer($replace);

return strtr($message, $replace);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion lang/en.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
'validate_max_len' => 'The {field} field needs to be {param} characters or less',
'validate_min_len' => 'The {field} field needs to be at least {param} characters',
'validate_exact_len' => 'The {field} field needs to be exactly {param} characters',
'validate_between_len' => 'The {field} field needs to be between {param[0]} and {param[1]} characters',
'validate_alpha' => 'The {field} field may only contain letters',
'validate_alpha_numeric' => 'The {field} field may only contain letters and numbers',
'validate_alpha_numeric_space' => 'The {field} field may only contain letters, numbers and spaces',
'validate_alpha_dash' => 'The {field} field may only contain letters and dashes',
'validate_alpha_numeric_dash' => 'The {field} field may only contain letters, numbers, dashes and underscores',
'validate_alpha_dash' => 'The {field} field may only contain letters, dashes and underscores',
'validate_alpha_space' => 'The {field} field may only contain letters and spaces',
'validate_numeric' => 'The {field} field must be a number',
'validate_integer' => 'The {field} field must be a number without a decimal',
Expand Down
18 changes: 0 additions & 18 deletions tests/FilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,6 @@ public function testCustomFilterIsSuccessfullyApplied()
], $result);
}

public function testCustomFilterWithParameters()
{
$this->markTestIncomplete('TODO');
GUMP::add_filter("custom", function($value, $params = null) {
return strtolower($value);
});

$result = $this->gump->filter([
'test' => ' text '
], [
'test' => 'trim|custom,hello,2'
]);

$this->assertEquals([
'test' => 'text'
], $result);
}

public function testNonexistentFilterThrowsException()
{
$this->expectException(Exception::class);
Expand Down
51 changes: 46 additions & 5 deletions tests/GetErrorsArrayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function testReturnsErrorsWithFieldAsKey()

public function testReturnsErrorsWithErrorMessageOfCustomValidator()
{
GUMP::add_validator("custom", function($field, $input, $param = NULL) {
GUMP::add_validator("custom", function($field, $input, $param = null) {
return $input[$field] === 'ok';
}, 'Custom error message');

Expand All @@ -65,23 +65,64 @@ public function testReturnsErrorsWithErrorMessageOfCustomValidator()
public function testErrorMessageReplacesReferencedFieldNameToo()
{
GUMP::set_field_name('test_number', 'Test Num.');
GUMP::set_field_name('test', 'The Other Test Field');
GUMP::set_field_name('other_field', 'The Other Test Field');

$result = $this->gump->validate([
'test_number' => '111',
'test' => '1112'
'other_field' => '1112'
], [
'test_number' => 'equalsfield,test'
'test_number' => 'equalsfield,other_field'
]);

$this->assertEquals([
'test_number' => 'The Test Num. field does not equal The Other Test Field field'
], $this->gump->get_errors_array());
}

public function testErrorMessagePropagatesParamsArrayKeysToErrorMessages()
{
GUMP::add_validator("num_index", function($field, $input, $param = null) {
return $input[$field] === 'ok';
}, 'Parameter one: {param[0]} and parameter two: {param[1]}');

GUMP::add_validator("text_index", function($field, $input, $param = null) {
return $input[$field] === 'ok';
}, 'Parameter one: {param[ten]} and parameter two: {param[twenty]}');

$result = $this->gump->validate([
'first_test' => 'notOk',
'second_test' => 'notOk',
], [
'first_test' => 'num_index,1;2',
'second_test' => ['text_index' => ['ten' => 10, 'twenty' => 20]],
]);

$this->assertEquals([
'first_test' => 'Parameter one: 1 and parameter two: 2',
'second_test' => 'Parameter one: 10 and parameter two: 20',
], $this->gump->get_errors_array());
}

public function testErrorMessageSplitsArrayParameterWithCommas()
{
GUMP::add_validator("custom", function($field, $input, $param = null) {
return $input[$field] === 'ok';
}, 'Separated by comma: {param}');

$result = $this->gump->validate([
'test_number' => 'notOk'
], [
'test_number' => 'custom,1;2'
]);

$this->assertEquals([
'test_number' => 'Separated by comma: 1, 2'
], $this->gump->get_errors_array());
}

public function testItThrowsExceptionWhenCustomValidatorFailsWithoutAnErrorMessageSet()
{
GUMP::add_validator("custom", function($field, $input, $param = NULL) {
GUMP::add_validator("custom", function($field, $input, $param = null) {
return $input[$field] === 'ok';
});

Expand Down
4 changes: 2 additions & 2 deletions tests/GetReadableErrorsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function testPrintsCustomFieldLabelsOnErrors()
], $this->gump->get_readable_errors());
}

public function testItThrowsExceptionWhenCustomValidatorFailsWithoutAnErrorMessageSet()
public function testItThrowsExceptionWhenCustomValidatorFailsAndDoesNotHaveErrorMessageSet()
{
GUMP::add_validator("custom", function($field, $input, $param = NULL) {
return $input[$field] === 'ok';
Expand Down Expand Up @@ -124,7 +124,7 @@ public function testWhenGumpInstanceIsCastedToStringItReturnsReadableErrorsInStr
'test_name' => '123',
], [
'test_number' => 'numeric',
'test_name' => 'valid_name'
'test_name' => 'valid_name|numeric'
]);

$this->assertEquals(
Expand Down

0 comments on commit 0dc626c

Please sign in to comment.