diff --git a/lib/Client.php b/lib/Client.php index 854c956..abf1e7c 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -374,7 +374,7 @@ public function loadFlags() { $payload = json_decode($this->localFlags(), true); - if (array_key_exists("detail", $payload)) { + if ($payload && array_key_exists("detail", $payload)) { throw new Exception($payload["detail"]); } diff --git a/lib/Consumer/ForkCurl.php b/lib/Consumer/ForkCurl.php index faa3717..5a16779 100644 --- a/lib/Consumer/ForkCurl.php +++ b/lib/Consumer/ForkCurl.php @@ -87,7 +87,7 @@ public function flushBatch($messages) // Send user agent in the form of {library_name}/{library_version} as per RFC 7231. $libName = $messages[0]['library']; $libVersion = $messages[0]['library_version']; - $cmd .= " -H 'User-Agent: ${libName}/${libVersion}'"; + $cmd .= " -H 'User-Agent: $libName/$libVersion'"; if (!$this->debug()) { $cmd .= " > /dev/null 2>&1 &"; diff --git a/lib/Consumer/Socket.php b/lib/Consumer/Socket.php index b178110..11e11c5 100644 --- a/lib/Consumer/Socket.php +++ b/lib/Consumer/Socket.php @@ -187,7 +187,7 @@ private function createBody($host, $content) $content_json = json_decode($content, true); $libName = $content_json['batch'][0]['library']; $libVersion = $content_json['batch'][0]['library_version']; - $req .= "User-Agent: ${libName}/${libVersion}\r\n"; + $req .= "User-Agent: $libName/$libVersion\r\n"; // Compress content if compress_request is true if ($this->compress_request) { diff --git a/lib/FeatureFlag.php b/lib/FeatureFlag.php index eb6e838..0120b0c 100644 --- a/lib/FeatureFlag.php +++ b/lib/FeatureFlag.php @@ -86,7 +86,7 @@ public static function matchProperty($property, $propertyValues) private static function hash($key, $distinctId, $salt = "") { $hashKey = sprintf("%s.%s%s", $key, $distinctId, $salt); - $hashVal = base_convert(substr(sha1(utf8_encode($hashKey)), 0, 15), 16, 10); + $hashVal = base_convert(substr(sha1($hashKey), 0, 15), 16, 10); return $hashVal / LONG_SCALE; } diff --git a/lib/PostHog.php b/lib/PostHog.php index 65ab781..252d71f 100644 --- a/lib/PostHog.php +++ b/lib/PostHog.php @@ -28,7 +28,6 @@ public static function init( if (null === $client) { $apiKey = $apiKey ?: getenv(self::ENV_API_KEY); - if (array_key_exists("host", $options)) { $options["host"] = self::cleanHost($options["host"]); } else { diff --git a/test/FeatureFlagTest.php b/test/FeatureFlagTest.php index b66046d..bdaa60b 100644 --- a/test/FeatureFlagTest.php +++ b/test/FeatureFlagTest.php @@ -13,6 +13,11 @@ class FeatureFlagMatch extends TestCase { + const FAKE_API_KEY = "random_key"; + + protected $http_client; + protected $client; + public function setUp(): void { date_default_timezone_set("UTC"); @@ -436,14 +441,16 @@ public function testMatchPropertyMathOperators(): void public function testFlagPersonProperties() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_REQUEST); + $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], $this->http_client, "test" ); + PostHog::init(null, null, $this->client); $this->assertTrue(PostHog::getFeatureFlag('person-flag', 'some-distinct-id', [], ["region" => "USA"])); @@ -454,7 +461,7 @@ public function testFlagGroupProperties() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_GROUP_PROPERTIES_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -475,7 +482,7 @@ public function testFlagComplexDefinition() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_COMPLEX_FLAG_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -496,7 +503,7 @@ public function testFlagFallbackToDecide() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::FALLBACK_TO_DECIDE_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -512,7 +519,7 @@ public function testFlagFallbackToDecide() public function testFeatureFlagDefaultsComeIntoPlayOnlyWhenDecideErrorsOut() { $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -528,7 +535,7 @@ public function testFlagExperienceContinuityNotEvaluatedLocally() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::EXPERIENCE_CONITNUITY_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -544,7 +551,7 @@ public function testGetAllFlagsWithFallback() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::MULTIPLE_FLAGS_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -564,7 +571,7 @@ public function testGetAllFlagsWithFallbackEmptyLocalFlags() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse:[]); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -583,7 +590,7 @@ public function testGetAllFlagsWithNoFallback() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse:MockedResponses::MULTIPLE_FLAGS_LOCAL_EVALUATE_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -602,7 +609,7 @@ public function testLoadFeatureFlags() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_GROUP_PROPERTIES_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -624,12 +631,12 @@ public function testLoadFeatureFlagsWrongKey() { self::expectException(Exception::class); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], null, - FAKE_API_KEY + self::FAKE_API_KEY ); PostHog::init(null, null, $this->client); } @@ -638,7 +645,7 @@ public function testSimpleFlag() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_SIMPLE_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -654,7 +661,7 @@ public function testFeatureFlagsDontFallbackToDecideWhenOnlyLocalEvaluationIsTru { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::FALLBACK_TO_DECIDE_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -712,7 +719,7 @@ public function testComputingInactiveFlagLocally() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_WITH_INACTIVE_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -733,7 +740,7 @@ public function testComputingFlagWithoutRolloutLocally() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_WITH_NO_ROLLOUT_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -753,7 +760,7 @@ public function testFlagWithVariantOverrides() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_VARIANT_OVERRIDES_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -770,7 +777,7 @@ public function testFlagWithClashingVariantOverrides() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_CLASHING_VARIANT_OVERRIDES_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -788,7 +795,7 @@ public function testFlagWithInvalidVariantOverrides() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_INVALID_VARIANT_OVERRIDES_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -805,7 +812,7 @@ public function testFlagWithMultipleVariantOverrides() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_MULTIPLE_VARIANT_OVERRIDES_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -823,7 +830,7 @@ public function testEventCalled() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::LOCAL_EVALUATION_SIMPLE_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -845,7 +852,7 @@ public function testFlagConsistency() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::SIMPLE_PARTIAL_REQUEST); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -1865,8 +1872,9 @@ public function testFlagConsistency() public function testMultivariateFlagConsistency() { $this->http_client = new MockedHttpClient(host: "app.posthog.com", flagEndpointResponse: MockedResponses::MULTIVARIATE_REQUEST); + $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], diff --git a/test/MockedHttpClient.php b/test/MockedHttpClient.php index 328e109..7ac4ab7 100644 --- a/test/MockedHttpClient.php +++ b/test/MockedHttpClient.php @@ -2,11 +2,14 @@ namespace PostHog\Test; +use Closure; use PostHog\HttpResponse; use PostHog\Test\Assets\MockedResponses; class MockedHttpClient extends \PostHog\HttpClient { + public $calls; + private $flagEndpointResponse; public function __construct( @@ -34,7 +37,7 @@ public function __construct( public function sendRequest(string $path, ?string $payload, array $extraHeaders = []): HttpResponse { if (!isset($this->calls)) { - $this->calls = array(); + $this->calls = []; } array_push($this->calls, array("path" => $path, "payload" => $payload)); diff --git a/test/PostHogTest.php b/test/PostHogTest.php index 2c5687c..fc7317a 100644 --- a/test/PostHogTest.php +++ b/test/PostHogTest.php @@ -7,16 +7,19 @@ use PostHog\Client; use PostHog\PostHog; -const FAKE_API_KEY = "random_key"; - class PostHogTest extends TestCase { + const FAKE_API_KEY = "random_key"; + + private $http_client; + private $client; + public function setUp(): void { date_default_timezone_set("UTC"); $this->http_client = new MockedHttpClient("app.posthog.com"); $this->client = new Client( - FAKE_API_KEY, + self::FAKE_API_KEY, [ "debug" => true, ], @@ -29,6 +32,7 @@ public function setUp(): void public function testInitWithParamApiKey(): void { $this->expectNotToPerformAssertions(); + PostHog::init("BrpS4SctoaCCsyjlnlun3OzyNJAafdlv__jUWaaJWXg", array("debug" => true)); } @@ -81,7 +85,7 @@ public function testCaptureWithSendFeatureFlagsOption(): void ), 1 => array( "path" => "/decide/?v=2", - "payload" => sprintf('{"api_key":"%s","distinct_id":"john"}', FAKE_API_KEY), + "payload" => sprintf('{"api_key":"%s","distinct_id":"john"}', self::FAKE_API_KEY), ), ) ); @@ -114,7 +118,7 @@ public function testIsFeatureEnabled() ), 1 => array( "path" => "/decide/?v=2", - "payload" => sprintf('{"api_key":"%s","distinct_id":"user-id"}', FAKE_API_KEY), + "payload" => sprintf('{"api_key":"%s","distinct_id":"user-id"}', self::FAKE_API_KEY), ), ) ); @@ -135,7 +139,7 @@ public function testIsFeatureEnabledGroups() "path" => "/decide/?v=2", "payload" => sprintf( '{"api_key":"%s","distinct_id":"user-id","groups":{"company":"id:5"}}', - FAKE_API_KEY + self::FAKE_API_KEY ), ), ) @@ -154,7 +158,7 @@ public function testGetFeatureFlag() ), 1 => array( "path" => "/decide/?v=2", - "payload" => sprintf('{"api_key":"%s","distinct_id":"user-id"}', FAKE_API_KEY), + "payload" => sprintf('{"api_key":"%s","distinct_id":"user-id"}', self::FAKE_API_KEY), ), ) ); @@ -183,7 +187,7 @@ public function testGetFeatureFlagGroups() "path" => "/decide/?v=2", "payload" => sprintf( '{"api_key":"%s","distinct_id":"user-id","groups":{"company":"id:5"}}', - FAKE_API_KEY + self::FAKE_API_KEY ), ), )