-
Notifications
You must be signed in to change notification settings - Fork 209
PHPC-1222: Implement accessor for error labels on exception classes #870
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,12 +23,88 @@ | |
|
||
#include "phongo_compat.h" | ||
#include "php_phongo.h" | ||
#include "php_array_api.h" | ||
|
||
zend_class_entry* php_phongo_runtimeexception_ce; | ||
|
||
static bool php_phongo_has_string_array_element(zval* labels, char* label TSRMLS_DC) | ||
{ | ||
HashTable* ht_data; | ||
|
||
if (Z_TYPE_P(labels) != IS_ARRAY) { | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I pondered whether a LogicException or something similar would work here, but it's probably best to keep There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is "added" referring to? I wasn't suggesting actually throwing, just explaining my thought process. I do think it's preferable to just return false here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added "added" to the wrong place I think. Want to say I added the test cases, perhaps? /me shrugs |
||
} | ||
|
||
ht_data = HASH_OF(labels); | ||
|
||
#if PHP_VERSION_ID >= 70000 | ||
{ | ||
zval* z_label; | ||
|
||
ZEND_HASH_FOREACH_VAL(ht_data, z_label) | ||
{ | ||
if ((Z_TYPE_P(z_label) == IS_STRING) && (strcmp(Z_STRVAL_P(z_label), label) == 0)) { | ||
return true; | ||
} | ||
} | ||
ZEND_HASH_FOREACH_END(); | ||
} | ||
#else | ||
{ | ||
HashPosition pos; | ||
zval** z_label; | ||
|
||
for ( | ||
zend_hash_internal_pointer_reset_ex(ht_data, &pos); | ||
zend_hash_get_current_data_ex(ht_data, (void**) &z_label, &pos) == SUCCESS; | ||
zend_hash_move_forward_ex(ht_data, &pos)) { | ||
|
||
if (Z_TYPE_PP(z_label) == IS_STRING) { | ||
if (strcmp(Z_STRVAL_PP(z_label), label) == 0) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
#endif | ||
|
||
return false; | ||
} | ||
|
||
/* {{{ proto bool MongoDB\Driver\Exception\RuntimeException::hasErrorLabel(string $label) | ||
Returns whether a specific error label has been set */ | ||
static PHP_METHOD(RuntimeException, hasErrorLabel) | ||
{ | ||
char* label; | ||
phongo_zpp_char_len label_len; | ||
zval* error_labels; | ||
#if PHP_VERSION_ID >= 70000 | ||
zval rv; | ||
#endif | ||
|
||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &label, &label_len) == FAILURE) { | ||
return; | ||
} | ||
|
||
#if PHP_VERSION_ID >= 70000 | ||
error_labels = zend_read_property(php_phongo_runtimeexception_ce, getThis(), ZEND_STRL("errorLabels"), 0, &rv TSRMLS_CC); | ||
#else | ||
error_labels = zend_read_property(php_phongo_runtimeexception_ce, getThis(), ZEND_STRL("errorLabels"), 0 TSRMLS_CC); | ||
#endif | ||
|
||
RETURN_BOOL(php_phongo_has_string_array_element(error_labels, label TSRMLS_CC)); | ||
} /* }}} */ | ||
|
||
ZEND_BEGIN_ARG_INFO_EX(ai_RuntimeException_hasErrorLabel, 0, 0, 1) | ||
ZEND_ARG_INFO(0, label) | ||
ZEND_END_ARG_INFO() | ||
|
||
/* {{{ MongoDB\Driver\Exception\RuntimeException function entries */ | ||
static zend_function_entry php_phongo_runtimeexception_me[] = { | ||
/* clang-format off */ | ||
PHP_ME(RuntimeException, hasErrorLabel, ai_RuntimeException_hasErrorLabel, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL) | ||
PHP_FE_END | ||
/* clang-format on */ | ||
}; | ||
/* }}} */ | ||
|
||
|
@@ -43,6 +119,8 @@ void php_phongo_runtimeexception_init_ce(INIT_FUNC_ARGS) /* {{{ */ | |
php_phongo_runtimeexception_ce = zend_register_internal_class_ex(&ce, spl_ce_RuntimeException, NULL TSRMLS_CC); | ||
#endif | ||
zend_class_implements(php_phongo_runtimeexception_ce TSRMLS_CC, 1, php_phongo_exception_ce); | ||
|
||
zend_declare_property_null(php_phongo_runtimeexception_ce, ZEND_STRL("errorLabels"), ZEND_ACC_PROTECTED TSRMLS_CC); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a particular reason this can't be private? I realize There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, that's the case:
It doesn't matter when I change it to use the base class (php_phongo_runtimeexception_ce). So, I think we're stuck with this. |
||
} /* }}} */ | ||
|
||
/* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
--TEST-- | ||
MongoDB\Driver\Exception\BulkWriteException::hasErrorLabel() | ||
--FILE-- | ||
<?php | ||
|
||
$exception = new MongoDB\Driver\Exception\BulkWriteException(); | ||
$labels = ['test', 'foo']; | ||
|
||
$reflection = new ReflectionClass($exception); | ||
|
||
$resultDocumentProperty = $reflection->getProperty('errorLabels'); | ||
$resultDocumentProperty->setAccessible(true); | ||
$resultDocumentProperty->setValue($exception, $labels); | ||
|
||
var_dump($exception->hasErrorLabel('foo')); | ||
var_dump($exception->hasErrorLabel('bar')); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
bool(true) | ||
bool(false) | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--TEST-- | ||
MongoDB\Driver\Exception\BulkWriteException::hasErrorLabel() with non-array values | ||
--FILE-- | ||
<?php | ||
|
||
$exception = new MongoDB\Driver\Exception\BulkWriteException(); | ||
$labels = 'shouldBeAnArray'; | ||
|
||
$reflection = new ReflectionClass($exception); | ||
|
||
$resultDocumentProperty = $reflection->getProperty('errorLabels'); | ||
$resultDocumentProperty->setAccessible(true); | ||
$resultDocumentProperty->setValue($exception, $labels); | ||
|
||
var_dump($exception->hasErrorLabel('bar')); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
bool(false) | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
--TEST-- | ||
MongoDB\Driver\Exception\CommandException::hasErrorLabel() | ||
--FILE-- | ||
<?php | ||
|
||
$exception = new MongoDB\Driver\Exception\CommandException(); | ||
$labels = ['test', 'foo']; | ||
|
||
$reflection = new ReflectionClass($exception); | ||
|
||
$resultDocumentProperty = $reflection->getProperty('errorLabels'); | ||
$resultDocumentProperty->setAccessible(true); | ||
$resultDocumentProperty->setValue($exception, $labels); | ||
|
||
var_dump($exception->hasErrorLabel('foo')); | ||
var_dump($exception->hasErrorLabel('bar')); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
bool(true) | ||
bool(false) | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--TEST-- | ||
MongoDB\Driver\Exception\CommandException::hasErrorLabel() with non-array values | ||
--FILE-- | ||
<?php | ||
|
||
$exception = new MongoDB\Driver\Exception\CommandException(); | ||
$labels = 'shouldBeAnArray'; | ||
|
||
$reflection = new ReflectionClass($exception); | ||
|
||
$resultDocumentProperty = $reflection->getProperty('errorLabels'); | ||
$resultDocumentProperty->setAccessible(true); | ||
$resultDocumentProperty->setValue($exception, $labels); | ||
|
||
var_dump($exception->hasErrorLabel('bar')); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
bool(false) | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
--TEST-- | ||
MongoDB\Driver\Exception\RuntimeException::hasErrorLabel() | ||
--FILE-- | ||
<?php | ||
|
||
$exception = new MongoDB\Driver\Exception\RuntimeException(); | ||
$labels = ['test', 'foo']; | ||
|
||
$reflection = new ReflectionClass($exception); | ||
|
||
$resultDocumentProperty = $reflection->getProperty('errorLabels'); | ||
$resultDocumentProperty->setAccessible(true); | ||
$resultDocumentProperty->setValue($exception, $labels); | ||
|
||
var_dump($exception->hasErrorLabel('foo')); | ||
var_dump($exception->hasErrorLabel('bar')); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
bool(true) | ||
bool(false) | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--TEST-- | ||
MongoDB\Driver\Exception\RuntimeException::hasErrorLabel() with non-array values | ||
--FILE-- | ||
<?php | ||
|
||
$exception = new MongoDB\Driver\Exception\RuntimeException(); | ||
$labels = 'shouldBeAnArray'; | ||
|
||
$reflection = new ReflectionClass($exception); | ||
|
||
$resultDocumentProperty = $reflection->getProperty('errorLabels'); | ||
$resultDocumentProperty->setAccessible(true); | ||
$resultDocumentProperty->setValue($exception, $labels); | ||
|
||
var_dump($exception->hasErrorLabel('bar')); | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECT-- | ||
bool(false) | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,9 +61,7 @@ try { | |
] ); | ||
$manager->executeCommand(DATABASE_NAME, $cmd, ['session' => $sessionB]); | ||
} catch (MongoDB\Driver\Exception\CommandException $e) { | ||
$rd = $e->getResultDocument(); | ||
|
||
echo (isset($rd->errorLabels) && in_array("TransientTransactionError", $rd->errorLabels)) ? | ||
echo $e->hasErrorLabel('TransientTransactionError') ? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before merging, will this PR have some tests demonstrating that we can call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had written these, but forgotten to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand correctly, this test was only using That may not be possible in this PR, as |
||
"found a TransientTransactionError" : "did NOT get a TransientTransactionError", "\n"; | ||
} | ||
?> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to use
phongo_throw_exception_from_bson_error_t(error TSRMLS_CC);
here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, because
phongo_throw_exception_from_bson_error_t
is now a wrapper forphongo_throw_exception_from_bson_error_and_reply_t
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that you added back
phongo_throw_exception_from_bson_error_t()
I think we can use it here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we can't, as
phongo_throw_exception_from_bson_error_t
is now a wrapper forphongo_throw_exception_from_bson_error_and_reply_t
: