From cb436a5b51628889681e657dfa328dcbadd2a1ae Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Thu, 20 Dec 2018 18:04:58 -0600 Subject: [PATCH 01/12] Add .gitignore --- .gitignore | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..83a3edd --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# phpize stuff +.libs +Makefile* +*.m4 +autom4te.cache +build +config.* +configure* +ibm_db2.la +ibm_db2.lo +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +modules +run-tests.php +tmp-php.ini + +# phpt generated files +tests/*.diff +tests/*.exp +tests/*.log +tests/*.out +tests/*.sh +tests/*.php + +# downloaded cli driver +clidriver + From b9bfd79bac8e08128ae003fcfe463d1a9cb255de Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Thu, 20 Dec 2018 18:06:23 -0600 Subject: [PATCH 02/12] Add TravisCI support This is similar to what I did for Python ibmdb https://github.com/ibmdb/python-ibmdb/pull/343 --- .travis.yml | 41 ++++++++++++++++++++++++++++++++++++++ tests/test_001_ConnDb.phpt | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..de03e08 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,41 @@ +language: php + +php: + - '7.2' + - '7.1' + - '7.0' + - '5.6' + +install: +- curl https://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/linuxx64_odbc_cli.tar.gz | tar -xz +- docker pull ibmcom/db2express-c +- docker run --name db2 -p 60000:50000 -e DB2INST1_PASSWORD=password -e LICENSE=accept -d ibmcom/db2express-c db2start +- docker ps -as +- docker exec -it db2 su - db2inst1 -c "db2 create db sample" + +before_script: +# Ensure that DB2CLIINIPATH gets passed to the tests +- echo 'variables_order = "EGPCS"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini + +script: +- phpize +- ./configure --with-IBM_DB2=$PWD/clidriver +- make +- | + cat < db2cli.ini + [SAMPLE] + Hostname=localhost + Protocol=TCPIP + Port=60000 + Database=sample + EOF +- cat db2cli.ini +# Ensure CLI can find the configuration +- export DB2CLIINIPATH=$PWD +# Ensure make returns non-zero when a test fails +- export REPORT_EXIT_STATUS=1 +# Save the report so we can print it if a test fails +- make test TESTS='-s report.txt' + +after_failure: +- cat report.txt diff --git a/tests/test_001_ConnDb.phpt b/tests/test_001_ConnDb.phpt index 8d6bac3..10db2df 100644 --- a/tests/test_001_ConnDb.phpt +++ b/tests/test_001_ConnDb.phpt @@ -13,7 +13,7 @@ if ($conn) { db2_close($conn); } else { - echo "Connection failed."; + echo "Connection failed: " . db2_conn_errormsg(); } ?> From da0e701802d90d53716edadc626b6e005975f045 Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Wed, 26 Dec 2018 23:22:23 -0600 Subject: [PATCH 03/12] Fix failing test cases Mostly involved finding resources relative to the script directory instead of from the current directory, which make test sets as the source directory. Instead of writing a file and then reading it back in to compare, just build up a string in memory and compare them. Connecting to a missing db alias returns an empty SQLSTATE. I'm not sure if/when that changed, but I've adjusted the code to handle either case. Finally, escape.dat was missing a \r in the file. --- tests/escape.dat | 6 ++---- tests/test_045_FetchArrayBinaryData.phpt | 14 ++++++-------- tests/test_048_FetchArrayBinaryData.phpt | 12 +++++------- tests/test_080_ConnWrongDbAlias.phpt | 5 ++--- tests/test_090_ConnmsgWrongDbAlias.phpt | 2 +- tests/test_1551_FetchAssocBinary.phpt | 12 +++++------- tests/test_163_FetchBothBinary.phpt | 12 +++++------- tests/test_320_EscapeString.phpt | 23 ++++++++++------------- 8 files changed, 36 insertions(+), 50 deletions(-) diff --git a/tests/escape.dat b/tests/escape.dat index 3de8098..110ffdb 100644 --- a/tests/escape.dat +++ b/tests/escape.dat @@ -1,10 +1,8 @@ Original: Some random special characters: - , - , \ , ' , " . + , , \ , ' , " . db2_escape_string: Some random special characters: - , - , \ , ' , " . + , , \ , ' , " . Original: Backslash (\). Single quote ('). Double quote (") db2_escape_string: Backslash (\). Single quote ('). Double quote (") diff --git a/tests/test_045_FetchArrayBinaryData.phpt b/tests/test_045_FetchArrayBinaryData.phpt index 1d4a6c5..8e94456 100644 --- a/tests/test_045_FetchArrayBinaryData.phpt +++ b/tests/test_045_FetchArrayBinaryData.phpt @@ -9,19 +9,17 @@ require_once('connection.inc'); $conn = db2_connect($db,$username,$password); -$orig = fopen("pic1.jpg", "rb"); -$new = fopen("pic1_out.jpg", "wb"); +$in_file = "pic1.jpg"; +$in = file_get_contents(dirname(__FILE__)."/".$in_file); $result = db2_exec($conn, "select photo_format, picture, length(picture) from emp_photo where photo_format='jpg' and empno='000130'"); $row = db2_fetch_array($result); +$out = ""; if ($row) { - fwrite($new, $row[1]); + $out .= $row[1]; } -$file0 = file_get_contents("pic1.jpg"); -$file1 = file_get_contents("pic1_out.jpg"); - -if(strcmp($file0, $file1) == 0) { +if(strcmp($in, $out) == 0) { echo "The files are the same...good."; } else { echo "The files are not the same...bad."; @@ -37,4 +35,4 @@ echo "\nIterated over $count rows."; ?> --EXPECT-- The files are the same...good. -Iterated over 8 rows. \ No newline at end of file +Iterated over 8 rows. diff --git a/tests/test_048_FetchArrayBinaryData.phpt b/tests/test_048_FetchArrayBinaryData.phpt index 8256c03..c040f48 100644 --- a/tests/test_048_FetchArrayBinaryData.phpt +++ b/tests/test_048_FetchArrayBinaryData.phpt @@ -9,19 +9,17 @@ require_once('connection.inc'); $conn = db2_connect($db,$username,$password); -$orig = fopen("spook.png", "rb"); -$new = fopen("spook_out.png", "wb"); +$in_file = "spook.png"; +$in = file_get_contents(dirname(__FILE__)."/".$in_file); $result = db2_exec($conn, "SELECT picture, LENGTH(picture) FROM animal_pics WHERE name = 'Spook'"); $row = db2_fetch_array($result); +$out = ""; if ($row) { - fwrite($new, $row[0]); + $out .= $row[0]; } -$file0 = file_get_contents("spook.png"); -$file1 = file_get_contents("spook_out.png"); - -if(strcmp($file0, $file1) == 0) { +if(strcmp($in, $out) == 0) { echo "The files are the same...good."; } else { echo "The files are not the same...bad."; diff --git a/tests/test_080_ConnWrongDbAlias.phpt b/tests/test_080_ConnWrongDbAlias.phpt index 72dc924..336b828 100644 --- a/tests/test_080_ConnWrongDbAlias.phpt +++ b/tests/test_080_ConnWrongDbAlias.phpt @@ -13,10 +13,9 @@ if ($conn) { echo "??? No way.\n"; } else { - $err = db2_conn_error(); - echo $err."\n"; + echo var_dump(db2_conn_error()); } ?> --EXPECTF-- -0800%d +string(5) "%s" diff --git a/tests/test_090_ConnmsgWrongDbAlias.phpt b/tests/test_090_ConnmsgWrongDbAlias.phpt index e9fc479..a260991 100644 --- a/tests/test_090_ConnmsgWrongDbAlias.phpt +++ b/tests/test_090_ConnmsgWrongDbAlias.phpt @@ -19,4 +19,4 @@ else { ?> --EXPECTF-- -[IBM][CLI Driver] %s SQLSTATE=%d SQLCODE=-%d +[IBM][CLI Driver] %s SQLCODE=-%d diff --git a/tests/test_1551_FetchAssocBinary.phpt b/tests/test_1551_FetchAssocBinary.phpt index c66f447..c10b63f 100644 --- a/tests/test_1551_FetchAssocBinary.phpt +++ b/tests/test_1551_FetchAssocBinary.phpt @@ -9,19 +9,17 @@ require_once('connection.inc'); $conn = db2_connect($db,$username,$password); -$orig = fopen("pic1.jpg", "rb"); -$new = fopen("pic1_out.jpg", "wb"); +$in_file = "pic1.jpg"; +$in = file_get_contents(dirname(__FILE__)."/".$in_file); $result = db2_exec($conn, "select photo_format, picture, length(picture) from emp_photo where photo_format='jpg' and empno='000130'"); $row = db2_fetch_assoc($result); +$out = ""; if ($row) { - fwrite($new, $row['PICTURE']); + $out .= $row['PICTURE']; } -$file0 = file_get_contents("pic1.jpg"); -$file1 = file_get_contents("pic1_out.jpg"); - -if(strcmp($file0, $file1) == 0) { +if(strcmp($in, $out) == 0) { echo "The files are the same...good."; } else { echo "The files are not the same...bad."; diff --git a/tests/test_163_FetchBothBinary.phpt b/tests/test_163_FetchBothBinary.phpt index 95cfcb1..9371468 100644 --- a/tests/test_163_FetchBothBinary.phpt +++ b/tests/test_163_FetchBothBinary.phpt @@ -9,19 +9,17 @@ require_once('connection.inc'); $conn = db2_connect($db,$username,$password); -$orig = fopen("pic1.jpg", "rb"); -$new = fopen("pic1_out.jpg", "wb"); +$in_file = "pic1.jpg"; +$in = file_get_contents(dirname(__FILE__)."/".$in_file); $result = db2_exec($conn, "select photo_format, picture, length(picture) from emp_photo where photo_format='jpg' and empno='000130'"); $row = db2_fetch_both($result); +$out = ""; if ($row) { - fwrite($new, $row['PICTURE']); + $out .= $row['PICTURE']; } -$file0 = file_get_contents("pic1.jpg"); -$file1 = file_get_contents("pic1_out.jpg"); - -if(strcmp($file0, $file1) == 0) { +if(strcmp($in, $out) == 0) { echo "The files are the same...good."; } else { echo "The files are not the same...bad."; diff --git a/tests/test_320_EscapeString.phpt b/tests/test_320_EscapeString.phpt index 147480b..9c09abb 100644 --- a/tests/test_320_EscapeString.phpt +++ b/tests/test_320_EscapeString.phpt @@ -14,9 +14,6 @@ if ($conn) { $create = 'CREATE TABLE escapeit(id INTEGER, info VARCHAR(200))'; $result = @db2_exec($conn, $create); - $orig = fopen("escape.dat", "rb"); - $new = fopen("escape_out.dat", "wb"); - $str[0] = "Some random special characters: \n , \r , \ , ' , \" ."; $str[1] = "Backslash (\). Single quote ('). Double quote (\")"; $str[2] = "The NULL character \\0 must be escaped manually"; @@ -26,8 +23,9 @@ if ($conn) { $str[6] = ""; $count = 0; + $out = ""; foreach( $str as $string ) { - $escaped = db2_escape_string($string); + $escaped = db2_escape_string($string); $insert = "INSERT INTO escapeit VALUES($count, '$escaped')"; db2_exec($conn, $insert); @@ -39,19 +37,18 @@ if ($conn) { $result = db2_fetch_array($stmt); $escapedFromDb = $result[0]; - fwrite($new, "\n"); - fwrite($new, "Original: " . $string); - fwrite($new, "\n"); - fwrite($new, "db2_escape_string: " . $escapedFromDb); - fwrite($new, "\n"); - + $out .= "\n"; + $out .= "Original: " . $string; + $out .= "\n"; + $out .= "db2_escape_string: " . $escapedFromDb; + $out .= "\n"; + $count++; } - $file0 = file_get_contents("escape.dat"); - $file1 = file_get_contents("escape_out.dat"); + $in = file_get_contents(dirname(__FILE__)."/escape.dat"); - if(strcmp($file0, $file1) == 0) { + if(strcmp($in, $out) == 0) { echo "The files are the same...good.\n"; } else { echo "The files are not the same...bad.\n"; From 8699b19ca88b05ee677e57899d832b77c6c1fecf Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Fri, 18 Jan 2019 12:55:01 -0600 Subject: [PATCH 04/12] Skip test_10353_MemLeak on PHP 5.6 due to segfault --- tests/test_10353_MemLeak.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_10353_MemLeak.phpt b/tests/test_10353_MemLeak.phpt index 45ae906..910dc87 100644 --- a/tests/test_10353_MemLeak.phpt +++ b/tests/test_10353_MemLeak.phpt @@ -3,6 +3,7 @@ IBM-DB2: PECL bug 10353 -- Memory leak testing --SKIPIF-- --FILE-- Date: Fri, 18 Jan 2019 12:55:29 -0600 Subject: [PATCH 05/12] Expect test_321_ResultFetchArraysLobsXMLTypes to fail The code does an SQLGetData, binding as SQL_CLOB_LOCATOR, but DB2 Connect CLI returns invalid conversion to bind a CLOB to a locator for some reason: 07006[IBM][CLI Driver] CLI0102E Invalid conversion. SQLSTATE=07006 The BLOB path works, using SQLGetData with SQL_BLOB_LOCATOR, so I'm not sure what's wrong with CLOBs. It seems like a bug, but I can't get it to work and the test predates the CI setup, so just expect it to fail for now. --- tests/test_321_ResultFetchArraysLobsXMLTypes.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_321_ResultFetchArraysLobsXMLTypes.phpt b/tests/test_321_ResultFetchArraysLobsXMLTypes.phpt index de39d8b..80a47b5 100644 --- a/tests/test_321_ResultFetchArraysLobsXMLTypes.phpt +++ b/tests/test_321_ResultFetchArraysLobsXMLTypes.phpt @@ -35,6 +35,8 @@ if ($conn) { } ?> +--XFAIL-- +SQLGetData as a CLOB locator returns conversion error for some reason. Probably a bug, but it predates the CI --EXPECT-- col 0: type:string xml value:[] false? col 1: type:string clob value:[a clob] false? From eb6d71ee8aec9dc7088a47e63c74e32962fd2e39 Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Mon, 28 Jan 2019 11:12:06 -0600 Subject: [PATCH 06/12] Fix use after free bug in db2_execute db2_execute calls _php_db2_execute_helper, which allocs curr->value if it is currently NULL. Later, _php_db2_set_symbol is called which frees tmp_curr->value, but it does not set it to NULL, which means on the next time through, _php_db2_execute_helper will skip allocating new memory and instead re-use a previously freed address. Found using Valgrind. --- ibm_db2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ibm_db2.c b/ibm_db2.c index 362f8d7..6b12b96 100644 --- a/ibm_db2.c +++ b/ibm_db2.c @@ -538,7 +538,6 @@ static void _php_db2_set_symbol(char * varname, zval *var TSRMLS_DC) } zval_ptr_dtor(*bind_data); ZVAL_COPY_VALUE(*bind_data, var); - efree(var); /* 1.9.9-zs7 */ #else ZEND_SET_SYMBOL(symbol_table_used, varname, var); #endif @@ -5289,6 +5288,11 @@ PHP_FUNCTION(db2_execute) tmp_curr->value->value.lval = (long)tmp_curr->long_value; } _php_db2_set_symbol(tmp_curr->varname, tmp_curr->value TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + efree(tmp_curr->value); /* 1.9.9-zs7 */ + tmp_curr->value = NULL; +#endif + default: break; } From 299ff6dc394d43dfcdfdc530b5e1e2552da759a7 Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Wed, 30 Jan 2019 14:34:08 -0600 Subject: [PATCH 07/12] Skip test 147 when running on PHP 7.1 with ZTS enabled See https://bugs.php.net/bug.php?id=77547 for more info --- tests/test_147_CallSPINAndOUTParamsMultipleTimes.phpt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_147_CallSPINAndOUTParamsMultipleTimes.phpt b/tests/test_147_CallSPINAndOUTParamsMultipleTimes.phpt index 2afbcfe..792dcaf 100644 --- a/tests/test_147_CallSPINAndOUTParamsMultipleTimes.phpt +++ b/tests/test_147_CallSPINAndOUTParamsMultipleTimes.phpt @@ -2,6 +2,12 @@ IBM-DB2: Call a stored procedure with IN and OUT parameters multiple times --SKIPIF-- +=') && + version_compare(PHP_VERSION, '7.2', '<')) { + die("skip: Test fails on PHP 7.1 with ZTS (https://bugs.php.net/bug.php?id=77547)"); +} +?> --FILE-- Date: Fri, 21 Dec 2018 15:49:49 -0600 Subject: [PATCH 08/12] Ensure no false-positives when run in the CI due to inability to connect Check for IBM_DB2_TEST_SKIP_CONNECT_FAILURE if it's set to an empty string or 0, instead of skipping the test it continues onward (and probaby fails). --- .travis.yml | 2 ++ tests/connection.inc | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index de03e08..cdaab11 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,8 @@ script: Database=sample EOF - cat db2cli.ini +# Ensure that tests are not skipped (false positive) due to bad configuration +- export IBM_DB2_TEST_SKIP_CONNECT_FAILURE=0 # Ensure CLI can find the configuration - export DB2CLIINIPATH=$PWD # Ensure make returns non-zero when a test fails diff --git a/tests/connection.inc b/tests/connection.inc index acddd0a..d043a61 100644 --- a/tests/connection.inc +++ b/tests/connection.inc @@ -39,9 +39,19 @@ else { date_default_timezone_set('UTC'); +$skip_on_connect_failure = getenv("IBM_DB2_TEST_SKIP_CONNECT_FAILURE") !== FALSE ? + getenv("IBM_DB2_TEST_SKIP_CONNECT_FAILURE") : true; + + // test connection ok $prepconn = db2_connect($database, $user, $password); -if (!$prepconn) die('skip'); -db2_close($prepconn); +if (!$prepconn) { + if($skip_on_connect_failure) die("skip - Couldn't connect"); +} +else { + db2_close($prepconn); +} + +unset($skip_on_connect_failure); ?> From 6151779916f6b4da51f95a1236aa4527b157020c Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Thu, 31 Jan 2019 00:25:06 -0600 Subject: [PATCH 09/12] PHP 7.3: Use new GC_SET_REFCOUNT macro See https://github.com/php/php-src/blob/php-7.3.0/UPGRADING.INTERNALS#L90-L96 Define 7.3 macro equivalents for 7.0-7.2 as well --- ibm_db2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ibm_db2.c b/ibm_db2.c index 6b12b96..80fc4c5 100644 --- a/ibm_db2.c +++ b/ibm_db2.c @@ -183,6 +183,12 @@ return #define zend_array HashTable #endif +#if PHP_VERSION_ID >= 70000 && PHP_VERSION_ID < 70300 +#define GC_ADDREF(p) ++GC_REFCOUNT(p) +#define GC_DELREF(p) --GC_REFCOUNT(p) +#define GC_SET_REFCOUNT(p, rc) GC_REFCOUNT(p) = rc +#endif + /* True global resources - no need for thread safety here */ static int le_conn_struct, le_stmt_struct, le_pconn_struct; @@ -2893,7 +2899,7 @@ static int _php_db2_connect_helper( INTERNAL_FUNCTION_PARAMETERS, conn_handle ** zend_resource newPersistentRes; newPersistentRes.type = le_pconn_struct; newPersistentRes.ptr = conn_res; - GC_REFCOUNT(&newPersistentRes) = 1; + GC_SET_REFCOUNT(&newPersistentRes, 1); if (zend_hash_str_update_mem(&EG(persistent_list), hKey, hKeyLen, &newPersistentRes, sizeof(newPersistentRes)) == NULL) { #else memset(&newEntry, 0, sizeof(newEntry)); From dfc43df5d2244786d8666cd4024e52ae04c31f36 Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Thu, 31 Jan 2019 00:28:21 -0600 Subject: [PATCH 10/12] PHP 7.3: Remove pointless IS_TYPE_COPYABLE checks See https://github.com/php/php-src/blob/php-7.3.0/UPGRADING.INTERNALS#L123-L128 It was only used in two places, which both were completely broken: (Z_TYPE_FLAGS_P(params) & (IS_TYPE_COPYABLE & !IS_TYPE_REFCOUNTED)) will always be false, since !IS_TYPE_REFCOUNTED is 0. I believe !IS_TYPE_REFCOUNTED was meant to be ~IS_TYPE_REFCOUNTED, but regardless the above document says that all checks for IS_TYPE_COPYABLE were replaced with IS_TYPE_ARRAY, which we're already checking so I just removed the pointless check for all releases. --- ibm_db2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ibm_db2.c b/ibm_db2.c index 80fc4c5..1b81619 100644 --- a/ibm_db2.c +++ b/ibm_db2.c @@ -5108,7 +5108,7 @@ PHP_FUNCTION(db2_execute) } #if PHP_MAJOR_VERSION >= 7 - if (parameters_array && Z_TYPE_P(parameters_array) == IS_ARRAY && (Z_TYPE_FLAGS_P(parameters_array) & (IS_TYPE_COPYABLE & !IS_TYPE_REFCOUNTED))) { + if (parameters_array && Z_TYPE_P(parameters_array) == IS_ARRAY) { SEPARATE_ARRAY(parameters_array); } #endif @@ -7827,7 +7827,7 @@ PHP_FUNCTION( db2_execute_many ) } #if PHP_MAJOR_VERSION >= 7 - if (params && Z_TYPE_P(params) == IS_ARRAY && (Z_TYPE_FLAGS_P(params) & (IS_TYPE_COPYABLE & !IS_TYPE_REFCOUNTED))) { + if (params && Z_TYPE_P(params) == IS_ARRAY) { SEPARATE_ARRAY(params); } #endif From 275c314b13a2aaafecee8c4ce6489fe42debe3ec Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Thu, 31 Jan 2019 00:37:20 -0600 Subject: [PATCH 11/12] PHP 7.3: boolean is now bool in warning message --- tests/test_10353_MemLeak.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_10353_MemLeak.phpt b/tests/test_10353_MemLeak.phpt index 910dc87..9da0b0c 100644 --- a/tests/test_10353_MemLeak.phpt +++ b/tests/test_10353_MemLeak.phpt @@ -139,7 +139,7 @@ Good, no memory leaks Good, no memory leaks Good, no memory leaks -Warning: db2_fetch_array() expects parameter 1 to be resource, boolean given in %s +Warning: db2_fetch_array() expects parameter 1 to be resource, bool%S given in %s Good, no memory leaks Good, no memory leaks Good, no memory leaks From 9476292eebc0ca335a99cc482229cd2fd965253a Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Thu, 31 Jan 2019 00:39:02 -0600 Subject: [PATCH 12/12] Enable PHP 7.3 in Travis CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cdaab11..43ae1be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: php php: + - '7.3' - '7.2' - '7.1' - '7.0'