Compare 316bca4 ... +9 ... d21925a

Coverage Reach
Auth/SignIn/GuzzleHandler.php Auth/SignIn/FailedToSignIn.php Auth/IdTokenVerifier.php Auth/ApiClient.php Auth/ActionCodeSettings/ValidatedActionCodeSettings.php Auth/ActionCodeSettings/RawActionCodeSettings.php Auth/CreateActionLink/GuzzleApiClientHandler.php Auth/CreateActionLink/FailedToCreateActionLink.php Auth/CreateActionLink/ApiRequest.php Auth/UserRecord.php Auth/SendActionLink/FailedToSendActionLink.php Auth/SendActionLink/ApiRequest.php Auth/SendActionLink/GuzzleApiClientHandler.php Auth/SignInResult.php Auth/CustomTokenViaGoogleIam.php Auth/SignInWithIdpCredentials.php Auth/SendActionLink.php Auth/CreateActionLink.php Auth/UserInfo.php Auth/UserMetaData.php Auth/SignInWithEmailAndOobCode.php Auth/SignInWithEmailAndPassword.php Auth/SignInWithRefreshToken.php Auth/SignInWithCustomToken.php Auth/DisabledLegacyIdTokenVerifier.php Auth/DisabledLegacyCustomTokenGenerator.php Auth/SignInAnonymously.php Messaging/CloudMessage.php Messaging/MulticastSendReport.php Messaging/Notification.php Messaging/Http/Request/SendMessages.php Messaging/Http/Request/SendMessageToTokens.php Messaging/Http/Request/ValidateMessage.php Messaging/Http/Request/SendMessage.php Messaging/SendReport.php Messaging/RegistrationTokens.php Messaging/AppInstance.php Messaging/MessageTarget.php Messaging/MessageData.php Messaging/AppInstanceApiClient.php Messaging/Condition.php Messaging/TopicSubscription.php Messaging/Topic.php Messaging/FcmOptions.php Messaging/ApiClient.php Messaging/RegistrationToken.php Messaging/ApnsConfig.php Messaging/AndroidConfig.php Messaging/WebPushConfig.php Messaging/TopicSubscriptions.php Messaging/Messages.php Messaging/RawMessageFromArray.php DynamicLink/AnalyticsInfo/GooglePlayAnalytics.php DynamicLink/AnalyticsInfo/ITunesConnectAnalytics.php DynamicLink/CreateDynamicLink.php DynamicLink/IOSInfo.php DynamicLink/EventStatistics.php DynamicLink/CreateDynamicLink/FailedToCreateDynamicLink.php DynamicLink/CreateDynamicLink/GuzzleApiClientHandler.php DynamicLink/CreateDynamicLink/ApiRequest.php DynamicLink/ShortenLongDynamicLink/FailedToShortenLongDynamicLink.php DynamicLink/ShortenLongDynamicLink/GuzzleApiClientHandler.php DynamicLink/ShortenLongDynamicLink/ApiRequest.php DynamicLink/GetStatisticsForDynamicLink/GuzzleApiClientHandler.php DynamicLink/GetStatisticsForDynamicLink/FailedToGetStatisticsForDynamicLink.php DynamicLink/GetStatisticsForDynamicLink/ApiRequest.php DynamicLink/SocialMetaTagInfo.php DynamicLink/AndroidInfo.php DynamicLink/ShortenLongDynamicLink.php DynamicLink/AnalyticsInfo.php DynamicLink/NavigationInfo.php DynamicLink/GetStatisticsForDynamicLink.php DynamicLink/DynamicLinkStatistics.php RemoteConfig/Parameter.php RemoteConfig/Template.php RemoteConfig/FindVersions.php RemoteConfig/ApiClient.php RemoteConfig/Version.php RemoteConfig/Condition.php RemoteConfig/ConditionalValue.php RemoteConfig/VersionNumber.php RemoteConfig/User.php RemoteConfig/TagColor.php RemoteConfig/UpdateType.php RemoteConfig/DefaultValue.php RemoteConfig/UpdateOrigin.php Database/Reference.php Database/Query/Filter/EndAt.php Database/Query/Filter/EqualTo.php Database/Query/Filter/StartAt.php Database/Query/Filter/LimitToLast.php Database/Query/Filter/LimitToFirst.php Database/Query/Filter/Shallow.php Database/Query/Sorter/OrderByChild.php Database/Query/Sorter/OrderByKey.php Database/Query/Sorter/OrderByValue.php Database/Query.php Database/ApiClient.php Database/Reference/Validator.php Database/Snapshot.php Database/Transaction.php Database/RuleSet.php Factory.php Auth.php Exception/AuthApiExceptionConverter.php Exception/MessagingApiExceptionConverter.php Exception/Database/TransactionFailed.php Exception/Database/ReferenceHasNotBeenSnapshotted.php Exception/Database/UnsupportedQuery.php Exception/Messaging/ServerUnavailable.php Exception/Messaging/AuthenticationError.php Exception/Messaging/InvalidMessage.php Exception/Messaging/MessagingError.php Exception/Messaging/NotFound.php Exception/Messaging/ServerError.php Exception/RemoteConfigApiExceptionConverter.php Exception/DatabaseApiExceptionConverter.php Exception/Auth/RevokedIdToken.php Exception/RemoteConfig/VersionNotFound.php Http/ResponseWithSubResponses.php Http/Middleware.php Http/RequestWithSubRequests.php Http/ErrorResponseParser.php Http/Requests.php Http/Responses.php Request/UpdateUser.php Request/CreateUser.php Messaging.php Value/Url.php Value/PhoneNumber.php Value/Email.php Value/ClearTextPassword.php Value/Uid.php Value/Provider.php DynamicLinks.php Util/DT.php Util/JSON.php Util/Deprecation.php ServiceAccount.php RemoteConfig.php Database.php DynamicLink.php Storage.php Project/ProjectId.php Firestore.php Util.php

Flags

Flags have been temporarily removed from this view while the flagging feature is refactored for better performance and user experience.

You can still use flags when viewing individual files. Flag-level thresholds will also remain on pull and merge requests in your repository provider.

More information can be found in our documentation.


@@ -4,8 +4,10 @@
Loading
4 4
5 5
namespace Kreait\Firebase\Http;
6 6
7 +
use GuzzleHttp;
7 8
use Psr\Http\Message\RequestInterface;
8 9
use Psr\Http\Message\ResponseInterface;
10 +
use Psr\Log\LoggerInterface;
9 11
10 12
final class Middleware
11 13
{
@@ -50,4 +52,30 @@
Loading
50 52
            };
51 53
        };
52 54
    }
55 +
56 +
    public static function log(LoggerInterface $logger, GuzzleHttp\MessageFormatter $formatter, string $logLevel, string $errorLogLevel): callable
57 +
    {
58 +
        return static function (callable $handler) use ($logger, $formatter, $logLevel, $errorLogLevel) {
59 +
            return static function ($request, array $options) use ($handler, $logger, $formatter, $logLevel, $errorLogLevel) {
60 +
                return $handler($request, $options)->then(
61 +
                    static function (ResponseInterface $response) use ($logger, $request, $formatter, $logLevel, $errorLogLevel) {
62 +
                        $message = $formatter->format($request, $response);
63 +
                        $messageLogLevel = $response->getStatusCode() >= 400 ? $errorLogLevel : $logLevel;
64 +
65 +
                        $logger->log($messageLogLevel, $message);
66 +
67 +
                        return $response;
68 +
                    },
69 +
                    static function (\Exception $reason) use ($logger, $request, $formatter, $errorLogLevel) {
70 +
                        $response = $reason instanceof GuzzleHttp\Exception\RequestException ? $reason->getResponse() : null;
71 +
                        $message = $formatter->format($request, $response, $reason);
72 +
73 +
                        $logger->log($errorLogLevel, $message, ['request' => $request, 'response' => $response]);
74 +
75 +
                        return GuzzleHttp\Promise\rejection_for($reason);
76 +
                    }
77 +
                );
78 +
            };
79 +
        };
80 +
    }
53 81
}

@@ -36,7 +36,10 @@
Loading
36 36
    /** @var array<int, array<string, string>> */
37 37
    private $events;
38 38
39 -
    private function __construct(array ...$events)
39 +
    /**
40 +
     * @param array<int, array<string, string>> $events
41 +
     */
42 +
    private function __construct(array $events)
40 43
    {
41 44
        $this->events = $events;
42 45
    }
@@ -46,7 +49,7 @@
Loading
46 49
     */
47 50
    public static function fromArray(array $events): self
48 51
    {
49 -
        return new self(...$events);
52 +
        return new self($events);
50 53
    }
51 54
52 55
    public function onAndroid(): self
@@ -105,7 +108,7 @@
Loading
105 108
106 109
    public function filter(callable $filter): self
107 110
    {
108 -
        return new self(...\array_filter($this->events, $filter));
111 +
        return new self(\array_filter($this->events, $filter));
109 112
    }
110 113
111 114
    /**

@@ -66,7 +66,7 @@
Loading
66 66
    private $signInHandler;
67 67
68 68
    /**
69 -
     * @param array<int, ApiClient|TokenGenerator|Verifier|SignInHandler> $x
69 +
     * @param iterable<ApiClient|TokenGenerator|Verifier|SignInHandler>|ApiClient|TokenGenerator|Verifier|SignInHandler $x
70 70
     *
71 71
     * @internal
72 72
     */

@@ -27,6 +27,13 @@
Loading
27 27
                throw new InvalidArgumentException('Message data must be a one-dimensional array of string(able) keys and values.');
28 28
            }
29 29
30 +
            if (self::isBinary((string) $value)) {
31 +
                throw new InvalidArgumentException(
32 +
                    "The message data field '{$key}' seems to contain binary data. As this can lead to broken messages, "
33 +
                    .'please convert it to a string representation first, e.g. with bin2hex() or base64encode().'
34 +
                );
35 +
            }
36 +
30 37
            $messageData->data[(string) $key] = (string) $value;
31 38
        }
32 39
@@ -48,4 +55,9 @@
Loading
48 55
    {
49 56
        return \is_null($value) || \is_scalar($value) || (\is_object($value) && \method_exists($value, '__toString'));
50 57
    }
58 +
59 +
    private static function isBinary(string $value): bool
60 +
    {
61 +
        return \mb_detect_encoding($value) === false;
62 +
    }
51 63
}

@@ -25,6 +25,7 @@
Loading
25 25
use Google\Cloud\Storage\StorageClient;
26 26
use GuzzleHttp\Client;
27 27
use GuzzleHttp\HandlerStack;
28 +
use GuzzleHttp\MessageFormatter;
28 29
use function GuzzleHttp\Psr7\uri_for;
29 30
use Kreait\Clock;
30 31
use Kreait\Clock\SystemClock;
@@ -41,6 +42,8 @@
Loading
41 42
use Kreait\Firebase\Value\Url;
42 43
use Psr\Cache\CacheItemPoolInterface;
43 44
use Psr\Http\Message\UriInterface;
45 +
use Psr\Log\LoggerInterface;
46 +
use Psr\Log\LogLevel;
44 47
use Psr\SimpleCache\CacheInterface;
45 48
use Throwable;
46 49
@@ -85,7 +88,7 @@
Loading
85 88
    protected $discoveryIsDisabled = false;
86 89
87 90
    /** @var bool */
88 -
    protected $debug = false;
91 +
    protected $guzzleDebugModeIsEnabled = false;
89 92
90 93
    /** @var string|null */
91 94
    protected $httpProxy;
@@ -99,6 +102,12 @@
Loading
99 102
    /** @var Clock */
100 103
    protected $clock;
101 104
105 +
    /** @var callable|null */
106 +
    protected $httpLogMiddleware;
107 +
108 +
    /** @var callable|null */
109 +
    protected $httpDebugLogMiddleware;
110 +
102 111
    public function __construct()
103 112
    {
104 113
        $this->clock = new SystemClock();
@@ -180,10 +189,42 @@
Loading
180 189
        return $factory;
181 190
    }
182 191
183 -
    public function withEnabledDebug(): self
192 +
    public function withEnabledDebug(?LoggerInterface $logger = null): self
184 193
    {
185 194
        $factory = clone $this;
186 -
        $factory->debug = true;
195 +
196 +
        if ($logger) {
197 +
            $factory = $factory->withHttpDebugLogger($logger);
198 +
        } else {
199 +
            Firebase\Util\Deprecation::trigger(__METHOD__.' without a '.LoggerInterface::class);
200 +
            // @codeCoverageIgnoreStart
201 +
            $factory->guzzleDebugModeIsEnabled = true;
202 +
            // @codeCoverageIgnoreEnd
203 +
        }
204 +
205 +
        return $factory;
206 +
    }
207 +
208 +
    public function withHttpLogger(LoggerInterface $logger, ?MessageFormatter $formatter = null, ?string $logLevel = null, ?string $errorLogLevel = null): self
209 +
    {
210 +
        $formatter = $formatter ?: new MessageFormatter();
211 +
        $logLevel = $logLevel ?: LogLevel::INFO;
212 +
        $errorLogLevel = $errorLogLevel ?: LogLevel::NOTICE;
213 +
214 +
        $factory = clone $this;
215 +
        $factory->httpLogMiddleware = Middleware::log($logger, $formatter, $logLevel, $errorLogLevel);
216 +
217 +
        return $factory;
218 +
    }
219 +
220 +
    public function withHttpDebugLogger(LoggerInterface $logger, ?MessageFormatter $formatter = null, ?string $logLevel = null, ?string $errorLogLevel = null): self
221 +
    {
222 +
        $formatter = $formatter ?: new MessageFormatter(MessageFormatter::DEBUG);
223 +
        $logLevel = $logLevel ?: LogLevel::INFO;
224 +
        $errorLogLevel = $errorLogLevel ?: LogLevel::NOTICE;
225 +
226 +
        $factory = clone $this;
227 +
        $factory->httpDebugLogMiddleware = Middleware::log($logger, $formatter, $logLevel, $errorLogLevel);
187 228
188 229
        return $factory;
189 230
    }
@@ -489,9 +530,11 @@
Loading
489 530
    {
490 531
        $config = $config ?? [];
491 532
492 -
        if ($this->debug) {
533 +
        // @codeCoverageIgnoreStart
534 +
        if ($this->guzzleDebugModeIsEnabled) {
493 535
            $config['debug'] = true;
494 536
        }
537 +
        // @codeCoverageIgnoreEnd
495 538
496 539
        if ($this->httpProxy) {
497 540
            $config['proxy'] = $this->httpProxy;
@@ -503,6 +546,16 @@
Loading
503 546
            $handler = HandlerStack::create($handler);
504 547
        }
505 548
549 +
        if ($handler instanceof HandlerStack) {
550 +
            if ($this->httpLogMiddleware) {
551 +
                $handler->push($this->httpLogMiddleware, 'http_logs');
552 +
            }
553 +
554 +
            if ($this->httpDebugLogMiddleware) {
555 +
                $handler->push($this->httpDebugLogMiddleware, 'http_debug_logs');
556 +
            }
557 +
        }
558 +
506 559
        if ($credentials = $this->getGoogleAuthTokenCredentials()) {
507 560
            $credentials = new FetchAuthTokenCache($credentials, null, $this->authTokenCache);
508 561
            $authTokenHandlerConfig = $config;

Everything is accounted for!

No changes detected that need to be reviewed.
What changes does Codecov check for?
Lines, not adjusted in diff, that have changed coverage data.
Files that introduced coverage data that had none before.
Files that have missing coverage data that once were tracked.
Files Complexity Coverage
src/Firebase ø 0.08% 96.03%
Project Totals (146 files) 1376 96.03%
Loading