From 728cc4f37585ba0a4906c77c2ba70bb76fa58b1d Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Tue, 29 Nov 2016 19:58:17 -0800 Subject: [PATCH 01/15] Moving to stable version of coveralls package and updating README --- README.md | 6 +++++- composer.json | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 38f783ff..66dc3f28 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,11 @@ This repository houses the PHP SDK for Optimizely Full Stack. ###Installing the SDK -The Optimizely PHP SDK will be available through [Composer](https://getcomposer.org/). Instructions coming soon. +The Optimizely PHP SDK can be installed through [Composer](https://getcomposer.org/). Please use the following command: + +``` +php composer.phar require optimizely/optimizely-sdk +``` ###Using the SDK See the Optimizely Full Stack [developer documentation](https://developers.optimizely.com/x/solutions/sdks/reference/?language=php) to learn how to set up your first Full Stack project and use the SDK. diff --git a/composer.json b/composer.json index 3f95ea60..2e61ca6b 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ }, "require-dev": { "phpunit/phpunit": "~4.8|~5.0", - "satooshi/php-coveralls": "dev-master" + "satooshi/php-coveralls": "v1.0.1" }, "autoload": { "psr-4": { From 7d403a0c6ac0add901903c8ec9a01725cf2bbea1 Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Fri, 2 Dec 2016 11:44:53 -0800 Subject: [PATCH 02/15] Test against 7.1 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e03ce72d..65bfeac2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ php: - '5.5' - '5.6' - '7.0' + - '7.1' - 'hhvm' before_install: - composer install --dev From 91b29d39b03b81e6ffe9a8d388166aacd9d37da6 Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Fri, 2 Dec 2016 11:43:54 -0800 Subject: [PATCH 03/15] Adding curl. WIP --- .../Event/Dispatcher/CurlEventDispatcher.php | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php diff --git a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php new file mode 100644 index 00000000..0a88ec09 --- /dev/null +++ b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php @@ -0,0 +1,33 @@ + Date: Wed, 7 Dec 2016 11:05:42 +0530 Subject: [PATCH 04/15] Curl based event dispatcher --- .../Event/Dispatcher/CurlEventDispatcher.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php index 0a88ec09..460e0e48 100644 --- a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php +++ b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php @@ -28,6 +28,17 @@ class CurlEventDispatcher implements EventDispatcherInterface { public function dispatchEvent(LogEvent $event) { - + $curl = curl_init(); + $options = [ + CURLOPT_URL => $event->getUrl(), + CURLOPT_HEADER => $event->getHeaders(), + CURLOPT_POSTFIELDS => http_build_query($event->getParams()), + CURLOPT_POST => 1, + CURLOPT_CONNECTTIMEOUT_MS => 1 + ]; + + curl_setopt_array($curl, $options); + curl_exec($curl); + curl_close($curl); } -} \ No newline at end of file +} From 2c3c99eb750325f6559aeedf98cbaac084fc352b Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Wed, 7 Dec 2016 11:40:00 +0530 Subject: [PATCH 05/15] Setting default values correctly --- src/Optimizely/ProjectConfig.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Optimizely/ProjectConfig.php b/src/Optimizely/ProjectConfig.php index be691260..beed9a14 100644 --- a/src/Optimizely/ProjectConfig.php +++ b/src/Optimizely/ProjectConfig.php @@ -129,11 +129,11 @@ public function __construct($datafile, $logger, $errorHandler) $this->_projectId = $config['projectId']; $this->_revision = $config['revision']; - $groups = $config['groups']; - $experiments = $config['experiments']; - $events = $config['events']; - $attributes = $config['attributes']; - $audiences = $config['audiences']; + $groups = $config['groups'] ?: []; + $experiments = $config['experiments'] ?: []; + $events = $config['events'] ?: []; + $attributes = $config['attributes'] ?: []; + $audiences = $config['audiences'] ?: []; $this->_groupIdMap = ConfigParser::generateMap($groups, 'id', Group::class); $this->_experimentKeyMap = ConfigParser::generateMap($experiments, 'key', Experiment::class); From f1f22e4b1a8a17b931a0e04eab2d671f4f65a9bc Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Wed, 7 Dec 2016 13:34:35 +0530 Subject: [PATCH 06/15] Fixing test --- tests/OptimizelyTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/OptimizelyTest.php b/tests/OptimizelyTest.php index 3fb5b1e7..161a93e8 100644 --- a/tests/OptimizelyTest.php +++ b/tests/OptimizelyTest.php @@ -143,8 +143,6 @@ public function testValidateInputsInvalidFileJsonValidationNotSkipped() 'Random datafile', false) ); - - $this->expectOutputRegex('/Provided "datafile" has invalid schema./'); } public function testValidateInputsInvalidFileJsonValidationSkipped() @@ -156,8 +154,6 @@ public function testValidateInputsInvalidFileJsonValidationSkipped() $validateInputsMethod->invoke(new Optimizely('Random datafile', null, null, null, true), 'Random datafile', true) ); - - $this->expectOutputRegex('/Provided "datafile" is in an invalid format./'); } public function testValidatePreconditionsExperimentNotRunning() From 7c9347c725653828354a6f137c50e2a3c0a6a4f1 Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Wed, 7 Dec 2016 13:44:18 +0530 Subject: [PATCH 07/15] Restoring test --- tests/OptimizelyTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/OptimizelyTest.php b/tests/OptimizelyTest.php index 161a93e8..5501ac03 100644 --- a/tests/OptimizelyTest.php +++ b/tests/OptimizelyTest.php @@ -143,6 +143,8 @@ public function testValidateInputsInvalidFileJsonValidationNotSkipped() 'Random datafile', false) ); + + $this->expectOutputRegex('/Provided "datafile" has invalid schema./'); } public function testValidateInputsInvalidFileJsonValidationSkipped() From 6b9441243f2c9169d48d5bec4fa05091b97ba569 Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Wed, 7 Dec 2016 20:11:41 +0530 Subject: [PATCH 08/15] WIP --- src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php index 460e0e48..7daa9b0c 100644 --- a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php +++ b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php @@ -31,9 +31,10 @@ public function dispatchEvent(LogEvent $event) $curl = curl_init(); $options = [ CURLOPT_URL => $event->getUrl(), - CURLOPT_HEADER => $event->getHeaders(), + CURLOPT_HTTPHEADER => $event->getHeaders(), CURLOPT_POSTFIELDS => http_build_query($event->getParams()), CURLOPT_POST => 1, + CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT_MS => 1 ]; From 23326c4a21d751df86b1e2df1b0b7e33c0fb3405 Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Sun, 11 Dec 2016 22:56:48 +0530 Subject: [PATCH 09/15] Updating curl dispatcher --- .../Event/Dispatcher/CurlEventDispatcher.php | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php index 7daa9b0c..fd3d92ea 100644 --- a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php +++ b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php @@ -28,18 +28,13 @@ class CurlEventDispatcher implements EventDispatcherInterface { public function dispatchEvent(LogEvent $event) { - $curl = curl_init(); - $options = [ - CURLOPT_URL => $event->getUrl(), - CURLOPT_HTTPHEADER => $event->getHeaders(), - CURLOPT_POSTFIELDS => http_build_query($event->getParams()), - CURLOPT_POST => 1, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_CONNECTTIMEOUT_MS => 1 - ]; - - curl_setopt_array($curl, $options); - curl_exec($curl); - curl_close($curl); + $cmd = "curl"; + $cmd.= " -X ".$event->getHttpVerb(); + foreach($event->getHeaders() as $type => $value) { + $cmd.= " -H '".$type.": ".$value."'"; + } + $cmd.= " -d '".json_encode($event->getParams())."'"; + $cmd.= " '".$event->getUrl()."' > /dev/null 2>&1 &"; + exec($cmd); } } From 72bb0621a55ecf046c850e59599c21b163901aaa Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Sun, 11 Dec 2016 23:14:46 +0530 Subject: [PATCH 10/15] Throwing exception --- src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php index fd3d92ea..1eeb1012 100644 --- a/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php +++ b/src/Optimizely/Event/Dispatcher/CurlEventDispatcher.php @@ -17,6 +17,7 @@ namespace Optimizely\Event\Dispatcher; +use Exception; use Optimizely\Event\LogEvent; /** @@ -35,6 +36,10 @@ public function dispatchEvent(LogEvent $event) } $cmd.= " -d '".json_encode($event->getParams())."'"; $cmd.= " '".$event->getUrl()."' > /dev/null 2>&1 &"; - exec($cmd); + exec($cmd, $output, $exit_code); + + if ($exit_code !== 0) { + throw new Exception('Curl command failed.'); + } } } From b2915246ed44c6c11cb27d41dff8fe3010b9224a Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Mon, 12 Dec 2016 10:05:54 +0530 Subject: [PATCH 11/15] Adding downloads badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 66dc3f28..ad07d982 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ #Optimizely PHP SDK [![Build Status](https://travis-ci.org/optimizely/php-sdk.svg?branch=master)](https://travis-ci.org/optimizely/php-sdk) [![Coverage Status](https://coveralls.io/repos/github/optimizely/php-sdk/badge.svg?branch=master)](https://coveralls.io/github/optimizely/php-sdk?branch=master) +[![Total Downloads](https://poser.pugx.org/optimizely/optimizely-sdk/downloads)](https://packagist.org/packages/optimizely/optimizely-sdk) [![Apache 2.0](https://img.shields.io/github/license/nebula-plugins/gradle-extra-configurations-plugin.svg)](http://www.apache.org/licenses/LICENSE-2.0) This repository houses the PHP SDK for Optimizely Full Stack. From 380b4af596693b44f16276fcee5438b6c522d563 Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Mon, 12 Dec 2016 12:04:23 +0530 Subject: [PATCH 12/15] Adding test with Not condition check --- tests/UtilsTests/ConditionEvaluatorTest.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/UtilsTests/ConditionEvaluatorTest.php b/tests/UtilsTests/ConditionEvaluatorTest.php index abcf61a8..2420a1da 100644 --- a/tests/UtilsTests/ConditionEvaluatorTest.php +++ b/tests/UtilsTests/ConditionEvaluatorTest.php @@ -2,14 +2,14 @@ /** * Copyright 2016, Optimizely * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the \"License\"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an \"AS IS\" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -29,7 +29,7 @@ class ConditionEvaluatorTest extends \PHPUnit_Framework_TestCase public function setUp() { $decoder = new ConditionDecoder(); - $conditions = "[\"and\", [\"or\", [\"or\", {\"name\": \"device_type\", \"type\": \"custom_attribute\", \"value\": \"iPhone\"}]], [\"or\", [\"or\", {\"name\": \"location\", \"type\": \"custom_attribute\", \"value\": \"San Francisco\"}]]]"; + $conditions = "[\"and\", [\"or\", [\"or\", {\"name\": \"device_type\", \"type\": \"custom_attribute\", \"value\": \"iPhone\"}]], [\"or\", [\"or\", {\"name\": \"location\", \"type\": \"custom_attribute\", \"value\": \"San Francisco\"}]], [\"or\", [\"not\", [\"or\", {\"name\": \"browser\", \"type\": \"custom_attribute\", \"value\": \"Firefox\"}]]]]"; $decoder->deserializeAudienceConditions($conditions); $this->conditionsList = $decoder->getConditionsList(); @@ -41,7 +41,7 @@ public function testEvaluateConditionsMatch() $userAttributes = [ 'device_type' => 'iPhone', 'location' => 'San Francisco', - 'browser' => 'chrome' + 'browser' => 'Chrome' ]; $this->assertTrue($this->conditionEvaluator->evaluate($this->conditionsList, $userAttributes)); @@ -51,8 +51,9 @@ public function testEvaluateConditionsMatch() public function testEvaluateConditionsDoNotMatch() { $userAttributes = [ + 'device_type' => 'iPhone', 'location' => 'San Francisco', - 'browser' => 'chrome' + 'browser' => 'Firefox' ]; $this->assertFalse($this->conditionEvaluator->evaluate($this->conditionsList, $userAttributes)); From 2d347fbbb4237d4cd3eaa427f2b4430ce022f15c Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Mon, 12 Dec 2016 12:44:25 +0530 Subject: [PATCH 13/15] adding 1 more test --- tests/OptimizelyTest.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/OptimizelyTest.php b/tests/OptimizelyTest.php index 5501ac03..fef5622f 100644 --- a/tests/OptimizelyTest.php +++ b/tests/OptimizelyTest.php @@ -275,6 +275,40 @@ public function testActivateInvalidAttributes() $this->assertNull($optlyObject->activate('test_experiment', 'test_user', 42)); } + public function testActivateUserInNoVariation() + { + $userAttributes = [ + 'device_type' => 'iPhone', + 'company' => 'Optimizely', + 'location' => 'San Francisco' + ]; + + $this->eventBuilderMock->expects($this->never()) + ->method('createImpressionEvent'); + + $this->loggerMock->expects($this->exactly(3)) + ->method('log'); + $this->loggerMock->expects($this->at(0)) + ->method('log') + ->with(Logger::DEBUG, 'Assigned bucket 8495 to user "not_in_variation_user".'); + $this->loggerMock->expects($this->at(1)) + ->method('log') + ->with(Logger::INFO, + 'User "not_in_variation_user" is in no variation.'); + $this->loggerMock->expects($this->at(2)) + ->method('log') + ->with(Logger::INFO, 'Not activating user "not_in_variation_user".'); + + $optlyObject = new Optimizely($this->datafile, new ValidEventDispatcher(), $this->loggerMock); + + $eventBuilder = new \ReflectionProperty(Optimizely::class, '_eventBuilder'); + $eventBuilder->setAccessible(true); + $eventBuilder->setValue($optlyObject, $this->eventBuilderMock); + + // Call activate + $this->assertNull($optlyObject->activate('test_experiment', 'not_in_variation_user', $userAttributes)); + } + public function testActivateNoAudienceNoAttributes() { $this->eventBuilderMock->expects($this->once()) From 8e042998a8f5d02c9fa3ed74a28f35b885c1deaf Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Mon, 12 Dec 2016 12:55:22 +0530 Subject: [PATCH 14/15] fixing license text --- tests/UtilsTests/ConditionEvaluatorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/UtilsTests/ConditionEvaluatorTest.php b/tests/UtilsTests/ConditionEvaluatorTest.php index 2420a1da..e70afe8a 100644 --- a/tests/UtilsTests/ConditionEvaluatorTest.php +++ b/tests/UtilsTests/ConditionEvaluatorTest.php @@ -2,14 +2,14 @@ /** * Copyright 2016, Optimizely * - * Licensed under the Apache License, Version 2.0 (the \"License\"); + * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an \"AS IS\" BASIS, + * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. From 4da89186e2a43c28982beea8c6275eea283f2b18 Mon Sep 17 00:00:00 2001 From: aliabbasrizvi Date: Tue, 13 Dec 2016 01:08:13 +0530 Subject: [PATCH 15/15] Bumping version for release --- CHANGELOG.md | 4 ++++ src/Optimizely/Event/Builder/EventBuilder.php | 2 +- tests/EventTests/EventBuilderTest.php | 12 ++++++------ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d05b8402..c5b7e037 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,6 @@ +## 1.0.0 +- General release of Optimizely X Full Stack PHP SDK. No breaking changes from previous version. +- Introduced curl based event dispatcher. + ## 0.1.0 - Beta release of the Optimizely X Full Stack PHP SDK. diff --git a/src/Optimizely/Event/Builder/EventBuilder.php b/src/Optimizely/Event/Builder/EventBuilder.php index 4accce93..9af7627e 100644 --- a/src/Optimizely/Event/Builder/EventBuilder.php +++ b/src/Optimizely/Event/Builder/EventBuilder.php @@ -33,7 +33,7 @@ class EventBuilder /** * @const string Version of the Optimizely PHP SDK. */ - const SDK_VERSION = '0.1.0'; + const SDK_VERSION = '1.0.0'; /** * @var string URL to send impression event to. diff --git a/tests/EventTests/EventBuilderTest.php b/tests/EventTests/EventBuilderTest.php index 58e78ea3..21f12049 100644 --- a/tests/EventTests/EventBuilderTest.php +++ b/tests/EventTests/EventBuilderTest.php @@ -48,7 +48,7 @@ public function testCreateImpressionEventNoAttributes() 'layerId' => '7719770039', 'visitorId' => 'testUserId', 'clientEngine' => 'php-sdk', - 'clientVersion' => '0.1.0', + 'clientVersion' => '1.0.0', 'timestamp' => time() * 1000, 'isGlobalHoldback' => false, 'userFeatures' => [], @@ -82,7 +82,7 @@ public function testCreateImpressionEventWithAttributes() 'layerId' => '7719770039', 'visitorId' => 'testUserId', 'clientEngine' => 'php-sdk', - 'clientVersion' => '0.1.0', + 'clientVersion' => '1.0.0', 'timestamp' => time() * 1000, 'isGlobalHoldback' => false, 'userFeatures' => [[ @@ -126,7 +126,7 @@ public function testCreateConversionEventNoAttributesNoValue() 'accountId' => '1592310167', 'visitorId' => 'testUserId', 'clientEngine' => 'php-sdk', - 'clientVersion' => '0.1.0', + 'clientVersion' => '1.0.0', 'userFeatures' => [], 'isGlobalHoldback' => false, 'timestamp' => time() * 1000, @@ -168,7 +168,7 @@ public function testCreateConversionEventWithAttributesNoValue() 'accountId' => '1592310167', 'visitorId' => 'testUserId', 'clientEngine' => 'php-sdk', - 'clientVersion' => '0.1.0', + 'clientVersion' => '1.0.0', 'isGlobalHoldback' => false, 'timestamp' => time() * 1000, 'eventFeatures' => [], @@ -221,7 +221,7 @@ public function testCreateConversionEventNoAttributesWithValue() 'accountId' => '1592310167', 'visitorId' => 'testUserId', 'clientEngine' => 'php-sdk', - 'clientVersion' => '0.1.0', + 'clientVersion' => '1.0.0', 'userFeatures' => [], 'isGlobalHoldback' => false, 'timestamp' => time() * 1000, @@ -266,7 +266,7 @@ public function testCreateConversionEventWithAttributesWithValue() 'accountId' => '1592310167', 'visitorId' => 'testUserId', 'clientEngine' => 'php-sdk', - 'clientVersion' => '0.1.0', + 'clientVersion' => '1.0.0', 'isGlobalHoldback' => false, 'timestamp' => time() * 1000, 'eventFeatures' => [],