├── .gitignore ├── src ├── Exceptions │ ├── InvalidArgumentException.php │ ├── InvalidEmailException.php │ ├── PermissionDeniedException.php │ ├── ResourceNotFoundException.php │ ├── WebhookSignatureException.php │ ├── ApiRateLimitExceededException.php │ ├── InternalServerErrorException.php │ ├── UnauthenticatedException.php │ ├── WebhookExpiredResponseException.php │ ├── MissingCalendlyTokenException.php │ ├── InvitationAlreadyAcceptedException.php │ └── ApiErrorException.php ├── Models │ ├── Guest.php │ ├── SchedulingLink.php │ ├── OrganizationMembership.php │ ├── RoutingFormSubmission.php │ ├── AvailabilityRule.php │ ├── EventTypeAvailableTime.php │ ├── RoutingForm.php │ ├── Profile.php │ ├── Invitee.php │ ├── OrganizationInvitation.php │ ├── IntrospectToken.php │ ├── UserAvailabilitySchedule.php │ ├── Organization.php │ ├── Event.php │ ├── User.php │ ├── EventType.php │ ├── UserBusyTime.php │ └── BaseModel.php ├── OAuth2 │ ├── Provider │ │ ├── CalendlyUser.php │ │ └── CalendlyOAuthProvider.php │ └── CalendlyOAuth.php ├── Webhooks │ ├── WebhookEvent.php │ ├── WebhookSubscription.php │ ├── WebhookSignature.php │ └── Webhook.php ├── Traits │ ├── Timeable.php │ ├── Deletable.php │ ├── Postable.php │ ├── NestedRelationListable.php │ └── Listable.php ├── Calendly.php ├── Utils │ └── PaginatedList.php └── CalendlyApi.php ├── composer.json ├── tests ├── CalendlyWebhookTest.php ├── CalendlyApiTest.php ├── CalendlyOAuthTest.php └── CalendlyResourceTest.php ├── LICENSE ├── README.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | .idea 3 | .phpunit.result.cache 4 | -------------------------------------------------------------------------------- /src/Exceptions/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | created_at); 14 | } 15 | 16 | public function getUpdateDate() { 17 | return new \DateTime($this->updated_at); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Exceptions/ApiErrorException.php: -------------------------------------------------------------------------------- 1 | details = $details; 14 | } 15 | 16 | public function getDetails(): array { 17 | return $this->details; 18 | } 19 | } -------------------------------------------------------------------------------- /src/Models/SchedulingLink.php: -------------------------------------------------------------------------------- 1 | request(static::$resource . "/" . $this->getId(), "DELETE", $options); 19 | return true; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Models/RoutingFormSubmission.php: -------------------------------------------------------------------------------- 1 | request(static::$resource, "POST", $options); 17 | if (isset($response["resource"])) { 18 | return new static($response["resource"]); 19 | } 20 | 21 | return null; 22 | } 23 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lobrs/calendly-sdk-php", 3 | "description": "Calendly API SDK PHP", 4 | "license": ["MIT"], 5 | "authors": [ 6 | { 7 | "name": "Loïc Brisset", 8 | "email": "loc.brisset@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "guzzlehttp/guzzle": "^7.4", 13 | "league/oauth2-client": "^2.6", 14 | "ext-json": "*", 15 | "php": ">=7.4" 16 | }, 17 | "require-dev": { 18 | "phpunit/phpunit": "^9.5", 19 | "mockery/mockery": "~1.5.1" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "LoBrs\\Calendly\\": "src/" 24 | } 25 | }, 26 | "autoload-dev": { 27 | "psr-4": { 28 | "LoBrs\\Calendly\\Test\\": "tests/" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Models/AvailabilityRule.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(WebhookSignature::class, $webhookSignature); 15 | $this->assertEquals($t, $webhookSignature->getTimestamp()); 16 | $this->assertEquals("v1", $webhookSignature->getVersion()); 17 | $this->assertEquals("5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd", $webhookSignature->getSignature()); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Models/EventTypeAvailableTime.php: -------------------------------------------------------------------------------- 1 | 29 | * @throws ApiErrorException|InvalidArgumentException 30 | */ 31 | public function getRoutingFormSubmissions(array $options = []): PaginatedList { 32 | return RoutingFormSubmission::paginate(array_merge([ 33 | "form" => $this->uri, 34 | ], $options)); 35 | } 36 | } -------------------------------------------------------------------------------- /src/Models/Profile.php: -------------------------------------------------------------------------------- 1 | owner)) { 26 | return null; 27 | } 28 | return Calendly::getClient()->getUser($this->owner); 29 | } 30 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Loïc Brisset 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Models/Invitee.php: -------------------------------------------------------------------------------- 1 | event); 40 | } 41 | 42 | public function getEvent(): ?Event { 43 | return Event::get($this->event); 44 | } 45 | } -------------------------------------------------------------------------------- /src/Traits/NestedRelationListable.php: -------------------------------------------------------------------------------- 1 | request(static::getResourceURI($parent_uuid), "GET", $options); 21 | if (isset($response["collection"])) { 22 | return static::collection($response["collection"]); 23 | } 24 | return []; 25 | } 26 | 27 | /** 28 | * URI to use in the API call. 29 | * 30 | * @param string $parent_uuid 31 | * @return string 32 | */ 33 | protected static function getResourceURI(string $parent_uuid): string { 34 | return static::getParentResource() . "/" . $parent_uuid . "/" . static::$resource; 35 | } 36 | 37 | abstract static function getParentResource(); 38 | } -------------------------------------------------------------------------------- /src/Traits/Listable.php: -------------------------------------------------------------------------------- 1 | request(static::getResourceURI(), "GET", $options); 19 | if (isset($response["collection"])) { 20 | return static::collection($response["collection"]); 21 | } 22 | return []; 23 | } 24 | 25 | /** 26 | * @param array $options 27 | * @return PaginatedList 28 | * @throws ApiErrorException|InvalidArgumentException 29 | */ 30 | public static function paginate(array $options = []): PaginatedList { 31 | $response = Calendly::getClient()->request(static::getResourceURI(), "GET", $options); 32 | if (isset($response["collection"])) { 33 | return static::pagination($response, $options); 34 | } 35 | return new PaginatedList([], $options); 36 | } 37 | 38 | protected static function getResourceURI() { 39 | return "/" . static::$resource; 40 | } 41 | } -------------------------------------------------------------------------------- /src/Models/OrganizationInvitation.php: -------------------------------------------------------------------------------- 1 | request(static::$resource . "/" . $this->organization . "/invitations/" . $this->getId(), "DELETE"); 38 | return true; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Models/IntrospectToken.php: -------------------------------------------------------------------------------- 1 | getField('organization'); 22 | if (empty($organization)) { 23 | return null; 24 | } 25 | return Organization::get($organization); 26 | } 27 | 28 | /** 29 | * @return User|null 30 | */ 31 | public function getOwner(): ?User { 32 | $owner = $this->getField('owner'); 33 | if (empty($owner)) { 34 | return null; 35 | } 36 | return User::get($owner); 37 | } 38 | } -------------------------------------------------------------------------------- /src/OAuth2/CalendlyOAuth.php: -------------------------------------------------------------------------------- 1 | client_id = $client_id; 17 | $this->client_secret = $client_secret; 18 | $this->redirect_uri = $redirect_uri; 19 | 20 | $this->provider = new CalendlyOAuthProvider([ 21 | "clientId" => $this->client_id, 22 | "clientSecret" => $this->client_secret, 23 | "redirectUri" => $this->redirect_uri, 24 | ]); 25 | } 26 | 27 | public function redirectToAuthorization() { 28 | header("Location: " . $this->getAuthorizationURL()); 29 | } 30 | 31 | public function getAuthorizationURL(array $options = []): string { 32 | return $this->provider->getAuthorizationUrl($options); 33 | } 34 | 35 | public function getAuthorizationCode() { 36 | return $_REQUEST["code"] ?? null; 37 | } 38 | 39 | public function getAccessToken(?string $authorization_code = null) { 40 | $this->provider->getAccessToken('authorization_code', [ 41 | 'code' => $authorization_code ?: $this->getAuthorizationCode(), 42 | 'redirect_uri' => $this->redirect_uri, 43 | ]); 44 | } 45 | } -------------------------------------------------------------------------------- /src/Calendly.php: -------------------------------------------------------------------------------- 1 | getField("user"); 33 | if (empty($user)) { 34 | return null; 35 | } 36 | 37 | return Calendly::getClient()->getUser($user); 38 | } 39 | 40 | /** 41 | * @return AvailabilityRule[] 42 | */ 43 | public function getRules(): array { 44 | return AvailabilityRule::collection((array)$this->rules); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/Models/Organization.php: -------------------------------------------------------------------------------- 1 | getId()); 27 | } 28 | 29 | /** 30 | * @return OrganizationMembership[] 31 | * @throws ApiErrorException|InvalidArgumentException 32 | */ 33 | public function getMemberShips() { 34 | return OrganizationMembership::getList($this->getId()); 35 | } 36 | 37 | /** 38 | * Invite a user to join an organization. 39 | * 40 | * @param string $email 41 | * @return ?OrganizationInvitation 42 | * @throws ApiErrorException|InvalidArgumentException 43 | */ 44 | public function invite(string $email) { 45 | $response = Calendly::getClient()->request(static::$resource . "/" . $this->getId() . "/invitations", "POST", [ 46 | "email" => $email, 47 | ]); 48 | if (isset($response["resource"])) { 49 | return new OrganizationInvitation($response["resource"]); 50 | } 51 | 52 | return null; 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/Models/Event.php: -------------------------------------------------------------------------------- 1 | status == "active"; 33 | } 34 | 35 | public function isCanceled(): bool { 36 | return $this->status == "canceled"; 37 | } 38 | 39 | public function getStartDate() { 40 | return new \DateTime($this->start_time); 41 | } 42 | 43 | public function getEndDate() { 44 | return new \DateTime($this->end_time); 45 | } 46 | 47 | public function getGuests() { 48 | return Guest::collection((array)$this->event_guests); 49 | } 50 | 51 | public function getEventTypeId(): string { 52 | return self::getIdFromUri($this->event_type); 53 | } 54 | 55 | public static function cancel(string $uuid, string $reason = "") { 56 | $response = Calendly::getClient()->request(static::$resource . "/$uuid/cancellation", "POST", [ 57 | "reason" => $reason, 58 | ]); 59 | if (isset($response["resource"])) { 60 | return $response["resource"]; 61 | } 62 | return false; 63 | } 64 | } -------------------------------------------------------------------------------- /src/Models/User.php: -------------------------------------------------------------------------------- 1 | getField("avatar_url"); 31 | } 32 | 33 | /** 34 | * The URL of the user's Calendly landing page (that lists all the user's event types) 35 | */ 36 | public function getSchedulingUrl(): ?string { 37 | return $this->getField("scheduling_url"); 38 | } 39 | 40 | /** 41 | * @param array $options 42 | * @return PaginatedList 43 | * @throws ApiErrorException|InvalidArgumentException 44 | */ 45 | public function getScheduledEvents(array $options = []) { 46 | return Event::paginate(array_merge([ 47 | "organization" => $this->current_organization, 48 | "user" => $this->uri, 49 | ], $options)); 50 | } 51 | 52 | /** 53 | * @return Organization|null 54 | * @throws ApiErrorException|InvalidArgumentException 55 | */ 56 | public function getCurrentOrganization(): ?Organization { 57 | if (!empty($this->getField("current_organization"))) { 58 | return Organization::get($this->current_organization); 59 | } 60 | 61 | return null; 62 | } 63 | } -------------------------------------------------------------------------------- /src/Utils/PaginatedList.php: -------------------------------------------------------------------------------- 1 | collection = $response["collection"] ?? []; 29 | $this->pagination = $response["pagination"] ?? []; 30 | $this->current_options = $current_options; 31 | $this->model = $model; 32 | } 33 | 34 | public function getCollection() { 35 | return $this->collection; 36 | } 37 | 38 | public function countResults(): int { 39 | return $this->pagination["count"] ?? 0; 40 | } 41 | 42 | public function getNextPageURL(): ?string { 43 | return $this->pagination["next_page"] ?? null; 44 | } 45 | 46 | public function getPreviousPageURL(): ?string { 47 | return $this->pagination["previous_page"] ?? null; 48 | } 49 | 50 | public function getNextPageToken(): ?string { 51 | return $this->pagination["next_page_token"] ?? null; 52 | } 53 | 54 | public function getPreviousPageToken(): ?string { 55 | return $this->pagination["previous_page_token"] ?? null; 56 | } 57 | 58 | public function next(array $options = []): ?PaginatedList { 59 | if (!empty($this->getNextPageToken()) && method_exists($this->model, "paginate")) { 60 | $options["page_token"] = $this->getNextPageToken(); 61 | return $this->model::paginate(array_merge($this->current_options, $options)); 62 | } 63 | 64 | return null; 65 | } 66 | 67 | public function previous(array $options = []): ?PaginatedList { 68 | if (!empty($this->getPreviousPageToken()) && method_exists($this->model, "paginate")) { 69 | $options["page_token"] = $this->getPreviousPageToken(); 70 | return $this->model::paginate(array_merge($this->current_options, $options)); 71 | } 72 | 73 | return null; 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /src/Webhooks/WebhookSubscription.php: -------------------------------------------------------------------------------- 1 | retry_started_at)) { 48 | return new \DateTime($this->retry_started_at); 49 | } 50 | 51 | return null; 52 | } 53 | 54 | /** 55 | * @return User|null 56 | * @throws ApiErrorException|InternalServerErrorException|InvalidArgumentException 57 | */ 58 | public function getCreator(): ?User { 59 | if (empty($this->creator)) { 60 | return null; 61 | } 62 | return User::get($this->creator); 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /src/Models/EventType.php: -------------------------------------------------------------------------------- 1 | getField($html ? "description_html" : "description_plain", ""); 49 | } 50 | 51 | /** 52 | * The publicly visible profile of a User or a Team that's associated with the Event Type. 53 | * 54 | * @return ?Profile 55 | */ 56 | public function getProfile(): ?Profile { 57 | $profile = $this->getField("profile"); 58 | if (empty($profile)) { 59 | // Some Event Types don't have profiles 60 | return null; 61 | } 62 | 63 | return new Profile((array)$profile); 64 | } 65 | 66 | /** 67 | * Creates a single-use scheduling link based on the Event Type. 68 | * 69 | * @param int $maxEventCount The max number of events that can be scheduled using this scheduling link. 70 | * @return BaseModel|null 71 | * @throws ApiErrorException|InvalidArgumentException 72 | */ 73 | public function createSchedulingLink(int $maxEventCount = 1): ?BaseModel { 74 | return SchedulingLink::create([ 75 | "max_event_count" => $maxEventCount, 76 | "owner" => $this->getId(), 77 | "owner_type" => "EventType", 78 | ]); 79 | } 80 | } -------------------------------------------------------------------------------- /src/Models/UserBusyTime.php: -------------------------------------------------------------------------------- 1 | start_time, new DateTimeZone('UTC')); 30 | } 31 | 32 | /** 33 | * @return DateTime The end time of the scheduled event in UTC time 34 | */ 35 | public function getEndTime(): DateTime { 36 | return new DateTime($this->end_time, new DateTimeZone('UTC')); 37 | } 38 | 39 | /** 40 | * @return DateTime The start time of the calendly event, as calculated by any "before" buffer set by the user in UTC time 41 | */ 42 | public function getBufferedStartTime(): DateTime { 43 | return new DateTime($this->buffered_start_time, new DateTimeZone('UTC')); 44 | } 45 | 46 | /** 47 | * @return DateTime The end time of the calendly event, as calculated by any "after" buffer set by the user in UTC time 48 | */ 49 | public function getBufferedEndTime(): DateTime { 50 | return new DateTime($this->buffered_end_time, new DateTimeZone('UTC')); 51 | } 52 | 53 | /** 54 | * @return Event|null 55 | * @throws ApiErrorException|InvalidArgumentException 56 | */ 57 | public function getEvent(): ?Event { 58 | $event = $this->getField('event'); 59 | if (empty($event) || empty($event['uri'])) { 60 | return null; 61 | } 62 | return Event::get($event['uri']); 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /src/Webhooks/WebhookSignature.php: -------------------------------------------------------------------------------- 1 | signature_timestamp = intval(explode('=', $header[0])[1] ?? null); 19 | [$this->signature_version, $this->signature] = explode('=', $header[1]); 20 | } 21 | 22 | /** 23 | * @param string $payload 24 | * @param string $header 25 | * @param string $secret 26 | * @param int $tolerance 27 | * @return WebhookSignature 28 | * @throws WebhookExpiredResponseException|WebhookSignatureException 29 | */ 30 | public static function verifySignature(string $payload, string $header, string $secret, int $tolerance): WebhookSignature { 31 | 32 | $sig = new WebhookSignature($header); 33 | 34 | if (empty($sig->signature)) { 35 | throw new WebhookSignatureException("No valid signature found"); 36 | } 37 | if (-1 === $sig->signature_timestamp || empty($sig->signature_timestamp)) { 38 | throw new WebhookExpiredResponseException('Signature header timestamp not found'); 39 | } 40 | 41 | $expected_signature = $sig->computeSignature($payload, $secret); 42 | 43 | if ($sig->signature !== $expected_signature) { 44 | throw new WebhookSignatureException('Invalid signature'); 45 | } 46 | 47 | if ($sig->signature_timestamp < time() - $tolerance) { 48 | throw new WebhookExpiredResponseException('Invalid Signature. The signature\'s timestamp is outside of the tolerance zone.'); 49 | } 50 | 51 | return $sig; 52 | } 53 | 54 | /** 55 | * @param string $payload 56 | * @param string $secret 57 | * @return string 58 | */ 59 | private function computeSignature(string $payload, string $secret): string { 60 | $data = $this->getTimestamp() . '.' . $payload; 61 | return \hash_hmac('sha256', $data, $secret); 62 | } 63 | 64 | public function getVersion(): string { 65 | return $this->signature_version; 66 | } 67 | 68 | public function getSignature(): string { 69 | return $this->signature; 70 | } 71 | 72 | public function getTimestamp(): int { 73 | return $this->signature_timestamp; 74 | } 75 | 76 | public static function getSignatureHeaders() { 77 | return $_SERVER['HTTP_CALENDLY_WEBHOOK_SIGNATURE'] ?? null; 78 | } 79 | } -------------------------------------------------------------------------------- /src/Models/BaseModel.php: -------------------------------------------------------------------------------- 1 | data = $response; 21 | } 22 | 23 | public function getId(): ?string { 24 | return $this->getField('id', static::getIdFromUri($this->uri ?? '')); 25 | } 26 | 27 | public function toArray(): array { 28 | return $this->data; 29 | } 30 | 31 | protected function getField(string $key, $default = null) { 32 | return $this->data[$key] ?? $default; 33 | } 34 | 35 | public function __get($name) { 36 | return $this->getField($name); 37 | } 38 | 39 | /** 40 | * Get resource model from uuid. 41 | * 42 | * @return static|null 43 | * @throws ApiErrorException|InvalidArgumentException|InternalServerErrorException 44 | */ 45 | public static function get(string $uuid) { 46 | if (empty(static::$resource)) { 47 | throw new InternalServerErrorException("Resource cannot be found for this model"); 48 | } 49 | if (strpos($uuid, "https://") === 0) { 50 | $uuid = static::getIdFromUri($uuid); 51 | } 52 | $response = Calendly::getClient()->request("/" . static::$resource . "/$uuid"); 53 | if (isset($response["resource"])) { 54 | return new static($response["resource"]); 55 | } 56 | return null; 57 | } 58 | 59 | /** 60 | * Returns a collection of the current model. 61 | * 62 | * @param array $list 63 | * @return static[] 64 | */ 65 | public static function collection(array $list): array { 66 | return array_map(function ($data) { 67 | return new static($data); 68 | }, $list); 69 | } 70 | 71 | /** 72 | * Create a paginated list from a collection response. 73 | * 74 | * @param array $response 75 | * @param array $options 76 | * @return PaginatedList 77 | */ 78 | public static function pagination(array $response, array $options = []): PaginatedList { 79 | $response["collection"] = static::collection($response["collection"]); 80 | return new PaginatedList($response, $options, static::class); 81 | } 82 | 83 | /** 84 | * Retrieve the last part of uri, which is the uuid. 85 | * 86 | * @param string $uri 87 | * @return mixed|string 88 | */ 89 | protected static function getIdFromUri(string $uri) { 90 | return array_reverse(explode("/", $uri))[0]; 91 | } 92 | } -------------------------------------------------------------------------------- /src/Webhooks/Webhook.php: -------------------------------------------------------------------------------- 1 | $url, 31 | "events" => $events, 32 | ]; 33 | if (is_string($params)) { 34 | $scope = strpos($params, "organization") !== false ? self::SCOPE_ORGANIZATION : self::SCOPE_USER; 35 | $params = [ 36 | "scope" => $scope, 37 | $scope => $params, 38 | ]; 39 | } 40 | 41 | $options = array_merge($options, $params); 42 | 43 | if (!empty($webhook_signing_key)) { 44 | $options['signing_key'] = $webhook_signing_key; 45 | } 46 | 47 | return WebhookSubscription::create($options); 48 | } 49 | 50 | /** 51 | * Returns the WebhookEvent corresponding to the provided JSON payload. 52 | * 53 | * @param string $payload Payload sent by Calendly 54 | * @param string $signature_header 55 | * @param string $secret_key Secret used to generate the signature 56 | * @param int $expire Maximum difference (seconds) allowed between the header's timestamp and the current time 57 | * @return WebhookEvent 58 | * @throws WebhookExpiredResponseException|WebhookSignatureException|UnexpectedValueException 59 | */ 60 | public static function readEvent( 61 | string $payload, 62 | string $signature_header, 63 | string $secret_key, 64 | int $expire = WebhookSignature::DEFAULT_EXPIRATION_TIME 65 | ): WebhookEvent { 66 | 67 | WebhookSignature::verifySignature($payload, $signature_header, $secret_key, $expire); 68 | 69 | $data = json_decode($payload, true); 70 | 71 | if ($data === null || !isset($data['payload'])) { 72 | throw new UnexpectedValueException('Invalid payload.'); 73 | } 74 | 75 | return new WebhookEvent($data); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /tests/CalendlyApiTest.php: -------------------------------------------------------------------------------- 1 | mockHandler = new MockHandler(); 24 | $httpClient = new Client([ 25 | 'handler' => HandlerStack::create($this->mockHandler), 26 | ]); 27 | 28 | $this->api = new CalendlyApi("secret", $httpClient); 29 | } 30 | 31 | public function testOkResponse() { 32 | 33 | $this->mockHandler->append(new Response(200, [ 34 | 'content-type' => 'application/json; charset=utf-8', 35 | ], '{"foo": "bar"}')); 36 | 37 | $response = $this->api->request("/foo"); 38 | $this->assertEquals("bar", $response["foo"]); 39 | $this->assertInstanceOf(ResponseInterface::class, $this->api->getLastResponse()); 40 | } 41 | 42 | public function testExceptionResponse() { 43 | 44 | $this->expectException(ApiErrorException::class); 45 | $this->mockHandler->append(new Response(400)); 46 | $this->api->request("/foo"); 47 | } 48 | 49 | public function testExceptionDetails() { 50 | 51 | $this->mockHandler->append(new Response(400, [ 52 | 'content-type' => 'application/json; charset=utf-8', 53 | ], '{"title": "Invalid Argument", "message": "There is an error", "details": [{"foo":"bar"}]}')); 54 | 55 | try { 56 | $this->api->request("/foo"); 57 | } catch (ApiErrorException $e) { 58 | $this->assertIsArray($e->getDetails()); 59 | $this->assertEquals("There is an error", $e->getMessage()); 60 | $this->assertInstanceOf(ResponseInterface::class, $this->api->getLastResponse()); 61 | } 62 | } 63 | 64 | public function testRateLimitHeader() { 65 | 66 | $this->mockHandler->append(new Response(429, [ 67 | 'X-RateLimit-Limit' => 1000, 68 | 'X-RateLimit-Remaining' => 0, 69 | 'X-RateLimit-Reset' => 60, 70 | ])); 71 | 72 | try { 73 | $this->api->request("/foo"); 74 | } catch (ApiErrorException $e) { 75 | $this->assertInstanceOf(ApiRateLimitExceededException::class, $e); 76 | } 77 | $this->assertEquals(1000, current($this->api->getLastResponse()->getHeader('X-RateLimit-Limit'))); 78 | $this->assertEquals(0, current($this->api->getLastResponse()->getHeader('X-RateLimit-Remaining'))); 79 | $this->assertEquals(60, current($this->api->getLastResponse()->getHeader('X-RateLimit-Reset'))); 80 | $this->assertEmpty($this->api->getLastResponse()->getHeader('InvalidHeader')); 81 | } 82 | 83 | } -------------------------------------------------------------------------------- /src/OAuth2/Provider/CalendlyOAuthProvider.php: -------------------------------------------------------------------------------- 1 | getStatusCode(), $data); 51 | } 52 | 53 | public function getAccessToken($grant = 'authorization_code', array $options = []) { 54 | return parent::getAccessToken($grant, $options); 55 | } 56 | 57 | /** 58 | * Use this endpoint to revoke an access/refresh token. 59 | * 60 | * @param string $token The access/refresh token provided by Calendly 61 | * @return bool 62 | */ 63 | public function revokeToken(string $token): bool { 64 | $options = [ 65 | 'client_id' => $this->clientId, 66 | 'client_secret' => $this->clientSecret, 67 | 'token' => $token, 68 | ]; 69 | $response = Calendly::request($this->getRevokeTokenUrl(), "POST", $options); 70 | 71 | return is_array($response); 72 | } 73 | 74 | /** 75 | * Use this endpoint to introspect an access/refresh token. 76 | * 77 | * @param string $token The access/refresh token provided by Calendly 78 | * @return IntrospectToken|null 79 | */ 80 | public function introspectToken(string $token): ?IntrospectToken { 81 | $options = [ 82 | 'client_id' => $this->clientId, 83 | 'client_secret' => $this->clientSecret, 84 | 'token' => $token, 85 | ]; 86 | $response = Calendly::request($this->getIntrospectTokenUrl(), "POST", $options); 87 | 88 | return empty($response) ? null : new IntrospectToken($response); 89 | } 90 | 91 | protected function createResourceOwner(array $response, AccessToken $token) { 92 | return new CalendlyUser($response['resource'] ?? []); 93 | } 94 | } -------------------------------------------------------------------------------- /tests/CalendlyOAuthTest.php: -------------------------------------------------------------------------------- 1 | provider = new CalendlyOAuthProvider([ 20 | "clientId" => "mock_client_id", 21 | "clientSecret" => "mock_secret", 22 | 'redirectUri' => 'none', 23 | ]); 24 | } 25 | 26 | public function testAuthorizationUrl() { 27 | $url = $this->provider->getAuthorizationUrl(); 28 | $uri = parse_url($url); 29 | parse_str($uri['query'], $query); 30 | 31 | $this->assertArrayHasKey('client_id', $query); 32 | $this->assertArrayHasKey('redirect_uri', $query); 33 | $this->assertArrayHasKey('state', $query); 34 | $this->assertArrayHasKey('response_type', $query); 35 | $this->assertArrayHasKey('approval_prompt', $query); 36 | $this->assertNotNull($this->provider->getState()); 37 | } 38 | 39 | public function testGetAuthorizationUrl() { 40 | $url = $this->provider->getAuthorizationUrl(); 41 | $uri = parse_url($url); 42 | 43 | $this->assertEquals('auth.calendly.com', $uri['host']); 44 | $this->assertEquals('/oauth/authorize', $uri['path']); 45 | } 46 | 47 | public function testGetBaseAccessTokenUrl() { 48 | $params = []; 49 | 50 | $url = $this->provider->getBaseAccessTokenUrl($params); 51 | $uri = parse_url($url); 52 | 53 | $this->assertEquals('auth.calendly.com', $uri['host']); 54 | $this->assertEquals('/oauth/token', $uri['path']); 55 | } 56 | 57 | protected function tearDown(): void { 58 | Mockery::close(); 59 | parent::tearDown(); 60 | } 61 | 62 | private function mockTokenResponse() { 63 | return [ 64 | "access_token" => "mock_access_token", 65 | "expires_in" => 315569260, 66 | ]; 67 | } 68 | 69 | public function testGetAccessToken() { 70 | $body = Utils::streamFor(json_encode($this->mockTokenResponse())); 71 | 72 | $response = Mockery::mock('Psr\Http\Message\ResponseInterface'); 73 | $response->shouldReceive('getBody')->andReturn($body); 74 | $response->shouldReceive('getHeader')->andReturn(['Content-Type' => 'application/json']); 75 | $response->shouldReceive('getStatusCode')->andReturn(200); 76 | 77 | $client = Mockery::mock('GuzzleHttp\ClientInterface'); 78 | $client->shouldReceive('send')->times(1)->andReturn($response); 79 | $this->provider->setHttpClient($client); 80 | 81 | $token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']); 82 | 83 | $this->assertEquals('mock_access_token', $token->getToken()); 84 | $this->assertNotNull($token->getExpires()); 85 | $this->assertNull($token->getRefreshToken()); 86 | } 87 | 88 | public function testUserData() 89 | { 90 | $token = Mockery::mock('League\OAuth2\Client\Token\AccessToken'); 91 | $user = $this->provider->getResourceOwner($token); 92 | $this->assertNotNull($user); 93 | $this->assertInstanceOf(CalendlyUser::class, $user); 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /tests/CalendlyResourceTest.php: -------------------------------------------------------------------------------- 1 | "https://api.calendly.com/users/AAAAAAAAAAAAAAAA", 15 | "name" => "John Doe", 16 | "slug" => "acmesales", 17 | "email" => "test@example.com", 18 | "scheduling_url" => "https://calendly.com/acmesales", 19 | "timezone" => "America/New York", 20 | "avatar_url" => "https://01234567890.cloudfront.net/uploads/user/avatar/0123456/a1b2c3d4.png", 21 | "created_at" => "2019-01-02T03:04:05.678123Z", 22 | "updated_at" => "2019-08-07T06:05:04.321123Z", 23 | "current_organization" => "https://api.calendly.com/organizations/AAAAAAAAAAAAAAAA", 24 | ]; 25 | $user = new User($data); 26 | $this->assertInstanceOf(User::class, $user); 27 | $this->assertEquals("John Doe", $user->name); 28 | $this->assertEquals("AAAAAAAAAAAAAAAA", $user->getId()); 29 | $this->assertEquals(new \DateTime("2019-01-02T03:04:05.678123Z"), $user->getCreationDate()); 30 | } 31 | 32 | public function testEventList() { 33 | $response = [ 34 | "collection" => [ 35 | [ 36 | "uri" => "https://api.calendly.com/scheduled_events/GBGBDCAADAEDCRZ2", 37 | "name" => "15 Minute Meeting", 38 | "status" => "active", 39 | "start_time" => "2019-08-24T14:15:22.123456Z", 40 | "end_time" => "2019-08-24T14:15:22.123456Z", 41 | "event_type" => "https://api.calendly.com/event_types/GBGBDCAADAEDCRZ2", 42 | "location" => [ 43 | "type" => "physical", 44 | "location" => "Calendly Office", 45 | ], 46 | "invitees_counter" => [ 47 | "total" => 0, 48 | "active" => 0, 49 | "limit" => 0, 50 | ], 51 | "created_at" => "2019-01-02T03:04:05.092125Z", 52 | "updated_at" => "2019-01-02T03:04:05.092125Z", 53 | "event_memberships" => [ 54 | [ 55 | "user" => "https://api.calendly.com/users/GBGBDCAADAEDCRZ2", 56 | ], 57 | ], 58 | "event_guests" => [ 59 | [ 60 | "email" => "user@example.com", 61 | "created_at" => "2022-04-21T17:10:48.484945Z", 62 | "updated_at" => "2022-04-21T17:11:01.758636Z", 63 | ], 64 | ], 65 | ], 66 | ], 67 | "pagination" => [ 68 | "count" => 1, 69 | "next_page" => "https://api.calendly.com/scheduled_events?count=1&page_token=sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi", 70 | "previous_page" => "https://api.calendly.com/scheduled_events?count=1&page_token=VJs2rfDYeY8ahZpq0QI1O114LJkNjd7H", 71 | "next_page_token" => "sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi", 72 | "previous_page_token" => "VJs2rfDYeY8ahZpq0QI1O114LJkNjd7H", 73 | ], 74 | ]; 75 | 76 | $data = Event::pagination($response); 77 | $this->assertNotNull($data); 78 | $this->assertInstanceOf(PaginatedList::class, $data); 79 | $this->assertIsArray($data->getCollection()); 80 | $this->assertNotEmpty($data->getCollection()); 81 | $this->assertInstanceOf(Event::class, $data->getCollection()[0]); 82 | $this->assertEquals(1, $data->countResults()); 83 | $this->assertEquals("https://api.calendly.com/scheduled_events?count=1&page_token=sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi", $data->getNextPageURL()); 84 | } 85 | } -------------------------------------------------------------------------------- /src/CalendlyApi.php: -------------------------------------------------------------------------------- 1 | token = $token; 34 | if ($httpClient) { 35 | $this->client = $httpClient; 36 | } else { 37 | $this->client = new Client([ 38 | "base_uri" => self::API_URL, 39 | ]); 40 | } 41 | } 42 | 43 | /** 44 | * @throws ApiErrorException|InvalidArgumentException 45 | */ 46 | public function request(string $uri, string $method = "GET", array $params = []) { 47 | $options[RequestOptions::HEADERS] = [ 48 | "Accept" => "application/json", 49 | "Authorization" => "Bearer " . $this->token, 50 | ]; 51 | if (strtolower($method) == "get") { 52 | $options[RequestOptions::QUERY] = $params; 53 | } else { 54 | $options[RequestOptions::JSON] = $params; 55 | } 56 | try { 57 | $this->response = $this->client->request($method, $uri, $options); 58 | } catch (GuzzleException $e) { 59 | $this->response = $e->getResponse(); 60 | } 61 | 62 | $data = json_decode($this->response->getBody(), true); 63 | $httpCode = $this->response->getStatusCode(); 64 | if ($httpCode > 299) { 65 | $message = $data['message'] ?? "An error occurred"; 66 | $details = $data['details'] ?? []; 67 | if (isset($data['title'])) { 68 | // get exception class from title 69 | $exceptionClassname = "LoBrs\\Calendly\\Exceptions\\" . str_replace(' ', '', 70 | ucwords(str_replace(['-', '_'], ' ', $data['title']))) . "Exception"; 71 | if (class_exists($exceptionClassname)) { 72 | throw new $exceptionClassname($message, $details); 73 | } 74 | } 75 | 76 | if ($httpCode == 500) { 77 | throw new InternalServerErrorException($message, $details); 78 | } 79 | if ($httpCode == 404) { 80 | throw new ResourceNotFoundException($message, $details); 81 | } 82 | if ($httpCode == 403) { 83 | throw new PermissionDeniedException($message, $details); 84 | } 85 | if ($httpCode == 401) { 86 | throw new UnauthenticatedException($message, $details); 87 | } 88 | if ($httpCode == 429) { 89 | throw new ApiRateLimitExceededException($message, $details); 90 | } 91 | 92 | // Default API error exception 93 | throw new ApiErrorException($message, $details); 94 | } 95 | 96 | return $data; 97 | } 98 | 99 | /** 100 | * @throws ApiErrorException|InvalidArgumentException 101 | */ 102 | public function me(): ?User { 103 | $response = $this->request("/users/me"); 104 | if (isset($response["resource"])) { 105 | return new User($response["resource"]); 106 | } 107 | return null; 108 | } 109 | 110 | /** 111 | * @throws ApiErrorException|InvalidArgumentException 112 | */ 113 | public function getOrganization(?string $organization_uuid = null): ?Organization { 114 | if (empty($organization_uuid)) { 115 | return $this->me()->getCurrentOrganization(); 116 | } 117 | 118 | return Organization::get($organization_uuid); 119 | } 120 | 121 | /** 122 | * @throws ApiErrorException|InvalidArgumentException 123 | */ 124 | public function getUser(?string $uuid = null): ?User { 125 | if (empty($uuid)) { 126 | return $this->me(); 127 | } 128 | 129 | return User::get($uuid); 130 | } 131 | 132 | /** 133 | * @throws ApiErrorException|InvalidArgumentException 134 | */ 135 | public function getEventTypes(array $options): Utils\PaginatedList { 136 | return EventType::paginate($options); 137 | } 138 | 139 | public function getLastResponse(): ResponseInterface { 140 | return $this->response; 141 | } 142 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Calendly PHP SDK 2 | 3 | PHP implementation of [Calendly API](https://developer.calendly.com/api-docs) (v2). 4 | 5 | 6 | ### Installation 7 | 8 | ``` 9 | composer require lobrs/calendly-sdk-php 10 | ``` 11 | 12 | ### Usage 13 | 14 | ```php 15 | \LoBrs\Calendly\Calendly::setToken($token); 16 | $currentUser = \LoBrs\Calendly\Calendly::me(); 17 | ``` 18 | 19 | #### Get user from UUID 20 | 21 | ```php 22 | $user = \LoBrs\Calendly\Models\User::get($uuid); 23 | ``` 24 | 25 | #### Get model list 26 | 27 | Returns an array of objects from the model class. 28 | 29 | ```php 30 | // List scheduled events from a user 31 | $scheduled_events = \Calendly\Models\Event::getList([ 32 | "user" => $user->uri 33 | ]); 34 | // List busy times from a user 35 | $busy_times = \Calendly\Models\UserBusyTime::getList([ 36 | "user" => $user->uri, 37 | "start_time" => date(DateTime::ATOM, strtotime("+1 minute")), 38 | "end_time" => date(DateTime::ATOM, strtotime("+7 days")), 39 | ]); 40 | ``` 41 | 42 | You can also use `paginate($options)` method, returning a `PaginatedList`. 43 | ```php 44 | $result = \Calendly\Models\Event::paginate([ 45 | "user" => $user->uri 46 | ]); 47 | 48 | echo $result->countResults() . " results \n"; 49 | echo $result->getNextPageURL(); 50 | 51 | // Request next page with the same options. 52 | $next_page_results = $result->next(); 53 | ``` 54 | 55 | Refer to the [Calendly API documentation](https://developer.calendly.com/api-docs) to find requests options. 56 | 57 | 58 | #### Currently supported models 59 | 60 | | Models | Get uuid | Paginate | Create | Delete | 61 | |-------------------------------|----------|----------|--------|--------| 62 | | Event | ✓ | ✓ | | | 63 | | EventType | ✓ | ✓ | | | 64 | | EventTypeAvailableTime | ✓ | | | | 65 | | Guest | ✓ | | | | 66 | | Invitee | ✓ | | | | 67 | | Organization | ✓ | | | | 68 | | OrganizationInvitation | ✓ | | | | 69 | | OrganizationMembership | ✓ | | | ✓ | 70 | | Profile | ✓ | | | | 71 | | RoutingForm | ✓ | ✓ | | | 72 | | RoutingFormSubmission | ✓ | ✓ | | | 73 | | SchedulingLink | ✓ | | ✓ | | 74 | | User | ✓ | | | | 75 | | UserAvailabilitySchedule | ✓ | | | | 76 | | UserBusyTime | ✓ | | | | 77 | | WebhookSubscription | ✓ | ✓ | ✓ | ✓ | 78 | 79 | 80 | #### Direct API request usage 81 | 82 | You can directly call the API using `Calendly::request($uri, "GET", $params)`, which returns the body of the response. 83 | 84 | 85 | ### Webhooks 86 | 87 | You can use `WebhookSubscription` Model directly to manage your Webhooks methods `getList`, `get`, `create` and `delete`. 88 | 89 | #### Webhook subscription 90 | 91 | We provide the `subscribe` helper method to add a new webhook. 92 | 93 | The 3rd parameter can be a `$uuid` referencing a user or organization uuid or an array of options. 94 | 95 | ```php 96 | \LoBrs\Calendly\Webhooks\Webhook::subscribe("https://example.com/my-webhook", [ 97 | 'invitee.created' 98 | ], [ 99 | 'user' => 'user_abc123', 100 | 'organization' => 'organization_abc123', 101 | 'scope' => 'organization', 102 | ], 'my-webhook-secret-key'); 103 | ``` 104 | 105 | To improve security, you can [sign your webhooks](https://developer.calendly.com/api-docs/ZG9jOjM2MzE2MDM4-webhook-signatures) 106 | by providing the webhook secret key parameter. 107 | 108 | #### Webhook payload example 109 | 110 | ```php 111 | $payload = @file_get_contents('php://input'); 112 | $header = $_SERVER['HTTP_CALENDLY_WEBHOOK_SIGNATURE']; 113 | try { 114 | $webhook = Webhook::readEvent($payload, $header, 'my-webhook-secret-key'); 115 | } catch (WebhookExpiredResponseException|WebhookSignatureException $e) {} 116 | ``` 117 | 118 | ### OAuth 119 | 120 | This package comes with an OAuth2 CLient, using [ThePhpLeague OAuth2 Client](https://github.com/thephpleague/oauth2-client) 121 | 122 | #### Usage flow 123 | 124 | ```php 125 | 126 | $provider = new CalendlyOAuthProvider([ 127 | "clientId" => env('CALENDLY_CLIENT'), 128 | "clientSecret" => env('CALENDLY_OAUTH_SECRET'), 129 | 'redirectUri' => env('CALENDLY_REDIRECT_URI'), 130 | ]); 131 | 132 | if (!isset($_GET['code'])) { 133 | 134 | // If we don't have an authorization code then get one 135 | $authUrl = $provider->getAuthorizationUrl(); 136 | 137 | header('Location: ' . $authUrl); 138 | exit; 139 | 140 | } else { 141 | 142 | // Try to get an access token (using the authorization code grant) 143 | $token = $provider->getAccessToken('authorization_code', [ 144 | 'code' => $_GET['code'], 145 | ]); 146 | 147 | try { 148 | // We got an access token, let's now get the user's details 149 | $user = $provider->getResourceOwner($token); 150 | 151 | print_r($user->toArray()); 152 | 153 | } catch (Exception $e) { 154 | exit('Failed to get user details'); 155 | } 156 | 157 | // Use this to interact with an API on the users behalf 158 | echo $token->getToken(); 159 | } 160 | ``` 161 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "c4794d1ac6a0796ca1d10f0ab1658aaa", 8 | "packages": [ 9 | { 10 | "name": "guzzlehttp/guzzle", 11 | "version": "7.8.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/guzzle/guzzle.git", 15 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", 20 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "ext-json": "*", 25 | "guzzlehttp/promises": "^1.5.3 || ^2.0.1", 26 | "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", 27 | "php": "^7.2.5 || ^8.0", 28 | "psr/http-client": "^1.0", 29 | "symfony/deprecation-contracts": "^2.2 || ^3.0" 30 | }, 31 | "provide": { 32 | "psr/http-client-implementation": "1.0" 33 | }, 34 | "require-dev": { 35 | "bamarni/composer-bin-plugin": "^1.8.2", 36 | "ext-curl": "*", 37 | "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", 38 | "php-http/message-factory": "^1.1", 39 | "phpunit/phpunit": "^8.5.36 || ^9.6.15", 40 | "psr/log": "^1.1 || ^2.0 || ^3.0" 41 | }, 42 | "suggest": { 43 | "ext-curl": "Required for CURL handler support", 44 | "ext-intl": "Required for Internationalized Domain Name (IDN) support", 45 | "psr/log": "Required for using the Log middleware" 46 | }, 47 | "type": "library", 48 | "extra": { 49 | "bamarni-bin": { 50 | "bin-links": true, 51 | "forward-command": false 52 | } 53 | }, 54 | "autoload": { 55 | "files": [ 56 | "src/functions_include.php" 57 | ], 58 | "psr-4": { 59 | "GuzzleHttp\\": "src/" 60 | } 61 | }, 62 | "notification-url": "https://packagist.org/downloads/", 63 | "license": [ 64 | "MIT" 65 | ], 66 | "authors": [ 67 | { 68 | "name": "Graham Campbell", 69 | "email": "hello@gjcampbell.co.uk", 70 | "homepage": "https://github.com/GrahamCampbell" 71 | }, 72 | { 73 | "name": "Michael Dowling", 74 | "email": "mtdowling@gmail.com", 75 | "homepage": "https://github.com/mtdowling" 76 | }, 77 | { 78 | "name": "Jeremy Lindblom", 79 | "email": "jeremeamia@gmail.com", 80 | "homepage": "https://github.com/jeremeamia" 81 | }, 82 | { 83 | "name": "George Mponos", 84 | "email": "gmponos@gmail.com", 85 | "homepage": "https://github.com/gmponos" 86 | }, 87 | { 88 | "name": "Tobias Nyholm", 89 | "email": "tobias.nyholm@gmail.com", 90 | "homepage": "https://github.com/Nyholm" 91 | }, 92 | { 93 | "name": "Márk Sági-Kazár", 94 | "email": "mark.sagikazar@gmail.com", 95 | "homepage": "https://github.com/sagikazarmark" 96 | }, 97 | { 98 | "name": "Tobias Schultze", 99 | "email": "webmaster@tubo-world.de", 100 | "homepage": "https://github.com/Tobion" 101 | } 102 | ], 103 | "description": "Guzzle is a PHP HTTP client library", 104 | "keywords": [ 105 | "client", 106 | "curl", 107 | "framework", 108 | "http", 109 | "http client", 110 | "psr-18", 111 | "psr-7", 112 | "rest", 113 | "web service" 114 | ], 115 | "support": { 116 | "issues": "https://github.com/guzzle/guzzle/issues", 117 | "source": "https://github.com/guzzle/guzzle/tree/7.8.1" 118 | }, 119 | "funding": [ 120 | { 121 | "url": "https://github.com/GrahamCampbell", 122 | "type": "github" 123 | }, 124 | { 125 | "url": "https://github.com/Nyholm", 126 | "type": "github" 127 | }, 128 | { 129 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", 130 | "type": "tidelift" 131 | } 132 | ], 133 | "time": "2023-12-03T20:35:24+00:00" 134 | }, 135 | { 136 | "name": "guzzlehttp/promises", 137 | "version": "2.0.2", 138 | "source": { 139 | "type": "git", 140 | "url": "https://github.com/guzzle/promises.git", 141 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" 142 | }, 143 | "dist": { 144 | "type": "zip", 145 | "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", 146 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", 147 | "shasum": "" 148 | }, 149 | "require": { 150 | "php": "^7.2.5 || ^8.0" 151 | }, 152 | "require-dev": { 153 | "bamarni/composer-bin-plugin": "^1.8.2", 154 | "phpunit/phpunit": "^8.5.36 || ^9.6.15" 155 | }, 156 | "type": "library", 157 | "extra": { 158 | "bamarni-bin": { 159 | "bin-links": true, 160 | "forward-command": false 161 | } 162 | }, 163 | "autoload": { 164 | "psr-4": { 165 | "GuzzleHttp\\Promise\\": "src/" 166 | } 167 | }, 168 | "notification-url": "https://packagist.org/downloads/", 169 | "license": [ 170 | "MIT" 171 | ], 172 | "authors": [ 173 | { 174 | "name": "Graham Campbell", 175 | "email": "hello@gjcampbell.co.uk", 176 | "homepage": "https://github.com/GrahamCampbell" 177 | }, 178 | { 179 | "name": "Michael Dowling", 180 | "email": "mtdowling@gmail.com", 181 | "homepage": "https://github.com/mtdowling" 182 | }, 183 | { 184 | "name": "Tobias Nyholm", 185 | "email": "tobias.nyholm@gmail.com", 186 | "homepage": "https://github.com/Nyholm" 187 | }, 188 | { 189 | "name": "Tobias Schultze", 190 | "email": "webmaster@tubo-world.de", 191 | "homepage": "https://github.com/Tobion" 192 | } 193 | ], 194 | "description": "Guzzle promises library", 195 | "keywords": [ 196 | "promise" 197 | ], 198 | "support": { 199 | "issues": "https://github.com/guzzle/promises/issues", 200 | "source": "https://github.com/guzzle/promises/tree/2.0.2" 201 | }, 202 | "funding": [ 203 | { 204 | "url": "https://github.com/GrahamCampbell", 205 | "type": "github" 206 | }, 207 | { 208 | "url": "https://github.com/Nyholm", 209 | "type": "github" 210 | }, 211 | { 212 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", 213 | "type": "tidelift" 214 | } 215 | ], 216 | "time": "2023-12-03T20:19:20+00:00" 217 | }, 218 | { 219 | "name": "guzzlehttp/psr7", 220 | "version": "2.6.2", 221 | "source": { 222 | "type": "git", 223 | "url": "https://github.com/guzzle/psr7.git", 224 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" 225 | }, 226 | "dist": { 227 | "type": "zip", 228 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", 229 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", 230 | "shasum": "" 231 | }, 232 | "require": { 233 | "php": "^7.2.5 || ^8.0", 234 | "psr/http-factory": "^1.0", 235 | "psr/http-message": "^1.1 || ^2.0", 236 | "ralouphie/getallheaders": "^3.0" 237 | }, 238 | "provide": { 239 | "psr/http-factory-implementation": "1.0", 240 | "psr/http-message-implementation": "1.0" 241 | }, 242 | "require-dev": { 243 | "bamarni/composer-bin-plugin": "^1.8.2", 244 | "http-interop/http-factory-tests": "^0.9", 245 | "phpunit/phpunit": "^8.5.36 || ^9.6.15" 246 | }, 247 | "suggest": { 248 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 249 | }, 250 | "type": "library", 251 | "extra": { 252 | "bamarni-bin": { 253 | "bin-links": true, 254 | "forward-command": false 255 | } 256 | }, 257 | "autoload": { 258 | "psr-4": { 259 | "GuzzleHttp\\Psr7\\": "src/" 260 | } 261 | }, 262 | "notification-url": "https://packagist.org/downloads/", 263 | "license": [ 264 | "MIT" 265 | ], 266 | "authors": [ 267 | { 268 | "name": "Graham Campbell", 269 | "email": "hello@gjcampbell.co.uk", 270 | "homepage": "https://github.com/GrahamCampbell" 271 | }, 272 | { 273 | "name": "Michael Dowling", 274 | "email": "mtdowling@gmail.com", 275 | "homepage": "https://github.com/mtdowling" 276 | }, 277 | { 278 | "name": "George Mponos", 279 | "email": "gmponos@gmail.com", 280 | "homepage": "https://github.com/gmponos" 281 | }, 282 | { 283 | "name": "Tobias Nyholm", 284 | "email": "tobias.nyholm@gmail.com", 285 | "homepage": "https://github.com/Nyholm" 286 | }, 287 | { 288 | "name": "Márk Sági-Kazár", 289 | "email": "mark.sagikazar@gmail.com", 290 | "homepage": "https://github.com/sagikazarmark" 291 | }, 292 | { 293 | "name": "Tobias Schultze", 294 | "email": "webmaster@tubo-world.de", 295 | "homepage": "https://github.com/Tobion" 296 | }, 297 | { 298 | "name": "Márk Sági-Kazár", 299 | "email": "mark.sagikazar@gmail.com", 300 | "homepage": "https://sagikazarmark.hu" 301 | } 302 | ], 303 | "description": "PSR-7 message implementation that also provides common utility methods", 304 | "keywords": [ 305 | "http", 306 | "message", 307 | "psr-7", 308 | "request", 309 | "response", 310 | "stream", 311 | "uri", 312 | "url" 313 | ], 314 | "support": { 315 | "issues": "https://github.com/guzzle/psr7/issues", 316 | "source": "https://github.com/guzzle/psr7/tree/2.6.2" 317 | }, 318 | "funding": [ 319 | { 320 | "url": "https://github.com/GrahamCampbell", 321 | "type": "github" 322 | }, 323 | { 324 | "url": "https://github.com/Nyholm", 325 | "type": "github" 326 | }, 327 | { 328 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", 329 | "type": "tidelift" 330 | } 331 | ], 332 | "time": "2023-12-03T20:05:35+00:00" 333 | }, 334 | { 335 | "name": "league/oauth2-client", 336 | "version": "2.7.0", 337 | "source": { 338 | "type": "git", 339 | "url": "https://github.com/thephpleague/oauth2-client.git", 340 | "reference": "160d6274b03562ebeb55ed18399281d8118b76c8" 341 | }, 342 | "dist": { 343 | "type": "zip", 344 | "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/160d6274b03562ebeb55ed18399281d8118b76c8", 345 | "reference": "160d6274b03562ebeb55ed18399281d8118b76c8", 346 | "shasum": "" 347 | }, 348 | "require": { 349 | "guzzlehttp/guzzle": "^6.0 || ^7.0", 350 | "paragonie/random_compat": "^1 || ^2 || ^9.99", 351 | "php": "^5.6 || ^7.0 || ^8.0" 352 | }, 353 | "require-dev": { 354 | "mockery/mockery": "^1.3.5", 355 | "php-parallel-lint/php-parallel-lint": "^1.3.1", 356 | "phpunit/phpunit": "^5.7 || ^6.0 || ^9.5", 357 | "squizlabs/php_codesniffer": "^2.3 || ^3.0" 358 | }, 359 | "type": "library", 360 | "extra": { 361 | "branch-alias": { 362 | "dev-2.x": "2.0.x-dev" 363 | } 364 | }, 365 | "autoload": { 366 | "psr-4": { 367 | "League\\OAuth2\\Client\\": "src/" 368 | } 369 | }, 370 | "notification-url": "https://packagist.org/downloads/", 371 | "license": [ 372 | "MIT" 373 | ], 374 | "authors": [ 375 | { 376 | "name": "Alex Bilbie", 377 | "email": "hello@alexbilbie.com", 378 | "homepage": "http://www.alexbilbie.com", 379 | "role": "Developer" 380 | }, 381 | { 382 | "name": "Woody Gilk", 383 | "homepage": "https://github.com/shadowhand", 384 | "role": "Contributor" 385 | } 386 | ], 387 | "description": "OAuth 2.0 Client Library", 388 | "keywords": [ 389 | "Authentication", 390 | "SSO", 391 | "authorization", 392 | "identity", 393 | "idp", 394 | "oauth", 395 | "oauth2", 396 | "single sign on" 397 | ], 398 | "support": { 399 | "issues": "https://github.com/thephpleague/oauth2-client/issues", 400 | "source": "https://github.com/thephpleague/oauth2-client/tree/2.7.0" 401 | }, 402 | "time": "2023-04-16T18:19:15+00:00" 403 | }, 404 | { 405 | "name": "paragonie/random_compat", 406 | "version": "v9.99.100", 407 | "source": { 408 | "type": "git", 409 | "url": "https://github.com/paragonie/random_compat.git", 410 | "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" 411 | }, 412 | "dist": { 413 | "type": "zip", 414 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", 415 | "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", 416 | "shasum": "" 417 | }, 418 | "require": { 419 | "php": ">= 7" 420 | }, 421 | "require-dev": { 422 | "phpunit/phpunit": "4.*|5.*", 423 | "vimeo/psalm": "^1" 424 | }, 425 | "suggest": { 426 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 427 | }, 428 | "type": "library", 429 | "notification-url": "https://packagist.org/downloads/", 430 | "license": [ 431 | "MIT" 432 | ], 433 | "authors": [ 434 | { 435 | "name": "Paragon Initiative Enterprises", 436 | "email": "security@paragonie.com", 437 | "homepage": "https://paragonie.com" 438 | } 439 | ], 440 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 441 | "keywords": [ 442 | "csprng", 443 | "polyfill", 444 | "pseudorandom", 445 | "random" 446 | ], 447 | "support": { 448 | "email": "info@paragonie.com", 449 | "issues": "https://github.com/paragonie/random_compat/issues", 450 | "source": "https://github.com/paragonie/random_compat" 451 | }, 452 | "time": "2020-10-15T08:29:30+00:00" 453 | }, 454 | { 455 | "name": "psr/http-client", 456 | "version": "1.0.3", 457 | "source": { 458 | "type": "git", 459 | "url": "https://github.com/php-fig/http-client.git", 460 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" 461 | }, 462 | "dist": { 463 | "type": "zip", 464 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", 465 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", 466 | "shasum": "" 467 | }, 468 | "require": { 469 | "php": "^7.0 || ^8.0", 470 | "psr/http-message": "^1.0 || ^2.0" 471 | }, 472 | "type": "library", 473 | "extra": { 474 | "branch-alias": { 475 | "dev-master": "1.0.x-dev" 476 | } 477 | }, 478 | "autoload": { 479 | "psr-4": { 480 | "Psr\\Http\\Client\\": "src/" 481 | } 482 | }, 483 | "notification-url": "https://packagist.org/downloads/", 484 | "license": [ 485 | "MIT" 486 | ], 487 | "authors": [ 488 | { 489 | "name": "PHP-FIG", 490 | "homepage": "https://www.php-fig.org/" 491 | } 492 | ], 493 | "description": "Common interface for HTTP clients", 494 | "homepage": "https://github.com/php-fig/http-client", 495 | "keywords": [ 496 | "http", 497 | "http-client", 498 | "psr", 499 | "psr-18" 500 | ], 501 | "support": { 502 | "source": "https://github.com/php-fig/http-client" 503 | }, 504 | "time": "2023-09-23T14:17:50+00:00" 505 | }, 506 | { 507 | "name": "psr/http-factory", 508 | "version": "1.0.2", 509 | "source": { 510 | "type": "git", 511 | "url": "https://github.com/php-fig/http-factory.git", 512 | "reference": "e616d01114759c4c489f93b099585439f795fe35" 513 | }, 514 | "dist": { 515 | "type": "zip", 516 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", 517 | "reference": "e616d01114759c4c489f93b099585439f795fe35", 518 | "shasum": "" 519 | }, 520 | "require": { 521 | "php": ">=7.0.0", 522 | "psr/http-message": "^1.0 || ^2.0" 523 | }, 524 | "type": "library", 525 | "extra": { 526 | "branch-alias": { 527 | "dev-master": "1.0.x-dev" 528 | } 529 | }, 530 | "autoload": { 531 | "psr-4": { 532 | "Psr\\Http\\Message\\": "src/" 533 | } 534 | }, 535 | "notification-url": "https://packagist.org/downloads/", 536 | "license": [ 537 | "MIT" 538 | ], 539 | "authors": [ 540 | { 541 | "name": "PHP-FIG", 542 | "homepage": "https://www.php-fig.org/" 543 | } 544 | ], 545 | "description": "Common interfaces for PSR-7 HTTP message factories", 546 | "keywords": [ 547 | "factory", 548 | "http", 549 | "message", 550 | "psr", 551 | "psr-17", 552 | "psr-7", 553 | "request", 554 | "response" 555 | ], 556 | "support": { 557 | "source": "https://github.com/php-fig/http-factory/tree/1.0.2" 558 | }, 559 | "time": "2023-04-10T20:10:41+00:00" 560 | }, 561 | { 562 | "name": "psr/http-message", 563 | "version": "2.0", 564 | "source": { 565 | "type": "git", 566 | "url": "https://github.com/php-fig/http-message.git", 567 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" 568 | }, 569 | "dist": { 570 | "type": "zip", 571 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", 572 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", 573 | "shasum": "" 574 | }, 575 | "require": { 576 | "php": "^7.2 || ^8.0" 577 | }, 578 | "type": "library", 579 | "extra": { 580 | "branch-alias": { 581 | "dev-master": "2.0.x-dev" 582 | } 583 | }, 584 | "autoload": { 585 | "psr-4": { 586 | "Psr\\Http\\Message\\": "src/" 587 | } 588 | }, 589 | "notification-url": "https://packagist.org/downloads/", 590 | "license": [ 591 | "MIT" 592 | ], 593 | "authors": [ 594 | { 595 | "name": "PHP-FIG", 596 | "homepage": "https://www.php-fig.org/" 597 | } 598 | ], 599 | "description": "Common interface for HTTP messages", 600 | "homepage": "https://github.com/php-fig/http-message", 601 | "keywords": [ 602 | "http", 603 | "http-message", 604 | "psr", 605 | "psr-7", 606 | "request", 607 | "response" 608 | ], 609 | "support": { 610 | "source": "https://github.com/php-fig/http-message/tree/2.0" 611 | }, 612 | "time": "2023-04-04T09:54:51+00:00" 613 | }, 614 | { 615 | "name": "ralouphie/getallheaders", 616 | "version": "3.0.3", 617 | "source": { 618 | "type": "git", 619 | "url": "https://github.com/ralouphie/getallheaders.git", 620 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 621 | }, 622 | "dist": { 623 | "type": "zip", 624 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 625 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 626 | "shasum": "" 627 | }, 628 | "require": { 629 | "php": ">=5.6" 630 | }, 631 | "require-dev": { 632 | "php-coveralls/php-coveralls": "^2.1", 633 | "phpunit/phpunit": "^5 || ^6.5" 634 | }, 635 | "type": "library", 636 | "autoload": { 637 | "files": [ 638 | "src/getallheaders.php" 639 | ] 640 | }, 641 | "notification-url": "https://packagist.org/downloads/", 642 | "license": [ 643 | "MIT" 644 | ], 645 | "authors": [ 646 | { 647 | "name": "Ralph Khattar", 648 | "email": "ralph.khattar@gmail.com" 649 | } 650 | ], 651 | "description": "A polyfill for getallheaders.", 652 | "support": { 653 | "issues": "https://github.com/ralouphie/getallheaders/issues", 654 | "source": "https://github.com/ralouphie/getallheaders/tree/develop" 655 | }, 656 | "time": "2019-03-08T08:55:37+00:00" 657 | }, 658 | { 659 | "name": "symfony/deprecation-contracts", 660 | "version": "v3.4.0", 661 | "source": { 662 | "type": "git", 663 | "url": "https://github.com/symfony/deprecation-contracts.git", 664 | "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" 665 | }, 666 | "dist": { 667 | "type": "zip", 668 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", 669 | "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", 670 | "shasum": "" 671 | }, 672 | "require": { 673 | "php": ">=8.1" 674 | }, 675 | "type": "library", 676 | "extra": { 677 | "branch-alias": { 678 | "dev-main": "3.4-dev" 679 | }, 680 | "thanks": { 681 | "name": "symfony/contracts", 682 | "url": "https://github.com/symfony/contracts" 683 | } 684 | }, 685 | "autoload": { 686 | "files": [ 687 | "function.php" 688 | ] 689 | }, 690 | "notification-url": "https://packagist.org/downloads/", 691 | "license": [ 692 | "MIT" 693 | ], 694 | "authors": [ 695 | { 696 | "name": "Nicolas Grekas", 697 | "email": "p@tchwork.com" 698 | }, 699 | { 700 | "name": "Symfony Community", 701 | "homepage": "https://symfony.com/contributors" 702 | } 703 | ], 704 | "description": "A generic function and convention to trigger deprecation notices", 705 | "homepage": "https://symfony.com", 706 | "support": { 707 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" 708 | }, 709 | "funding": [ 710 | { 711 | "url": "https://symfony.com/sponsor", 712 | "type": "custom" 713 | }, 714 | { 715 | "url": "https://github.com/fabpot", 716 | "type": "github" 717 | }, 718 | { 719 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 720 | "type": "tidelift" 721 | } 722 | ], 723 | "time": "2023-05-23T14:45:45+00:00" 724 | } 725 | ], 726 | "packages-dev": [ 727 | { 728 | "name": "doctrine/instantiator", 729 | "version": "2.0.0", 730 | "source": { 731 | "type": "git", 732 | "url": "https://github.com/doctrine/instantiator.git", 733 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" 734 | }, 735 | "dist": { 736 | "type": "zip", 737 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", 738 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", 739 | "shasum": "" 740 | }, 741 | "require": { 742 | "php": "^8.1" 743 | }, 744 | "require-dev": { 745 | "doctrine/coding-standard": "^11", 746 | "ext-pdo": "*", 747 | "ext-phar": "*", 748 | "phpbench/phpbench": "^1.2", 749 | "phpstan/phpstan": "^1.9.4", 750 | "phpstan/phpstan-phpunit": "^1.3", 751 | "phpunit/phpunit": "^9.5.27", 752 | "vimeo/psalm": "^5.4" 753 | }, 754 | "type": "library", 755 | "autoload": { 756 | "psr-4": { 757 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 758 | } 759 | }, 760 | "notification-url": "https://packagist.org/downloads/", 761 | "license": [ 762 | "MIT" 763 | ], 764 | "authors": [ 765 | { 766 | "name": "Marco Pivetta", 767 | "email": "ocramius@gmail.com", 768 | "homepage": "https://ocramius.github.io/" 769 | } 770 | ], 771 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 772 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 773 | "keywords": [ 774 | "constructor", 775 | "instantiate" 776 | ], 777 | "support": { 778 | "issues": "https://github.com/doctrine/instantiator/issues", 779 | "source": "https://github.com/doctrine/instantiator/tree/2.0.0" 780 | }, 781 | "funding": [ 782 | { 783 | "url": "https://www.doctrine-project.org/sponsorship.html", 784 | "type": "custom" 785 | }, 786 | { 787 | "url": "https://www.patreon.com/phpdoctrine", 788 | "type": "patreon" 789 | }, 790 | { 791 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 792 | "type": "tidelift" 793 | } 794 | ], 795 | "time": "2022-12-30T00:23:10+00:00" 796 | }, 797 | { 798 | "name": "hamcrest/hamcrest-php", 799 | "version": "v2.0.1", 800 | "source": { 801 | "type": "git", 802 | "url": "https://github.com/hamcrest/hamcrest-php.git", 803 | "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" 804 | }, 805 | "dist": { 806 | "type": "zip", 807 | "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", 808 | "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", 809 | "shasum": "" 810 | }, 811 | "require": { 812 | "php": "^5.3|^7.0|^8.0" 813 | }, 814 | "replace": { 815 | "cordoval/hamcrest-php": "*", 816 | "davedevelopment/hamcrest-php": "*", 817 | "kodova/hamcrest-php": "*" 818 | }, 819 | "require-dev": { 820 | "phpunit/php-file-iterator": "^1.4 || ^2.0", 821 | "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" 822 | }, 823 | "type": "library", 824 | "extra": { 825 | "branch-alias": { 826 | "dev-master": "2.1-dev" 827 | } 828 | }, 829 | "autoload": { 830 | "classmap": [ 831 | "hamcrest" 832 | ] 833 | }, 834 | "notification-url": "https://packagist.org/downloads/", 835 | "license": [ 836 | "BSD-3-Clause" 837 | ], 838 | "description": "This is the PHP port of Hamcrest Matchers", 839 | "keywords": [ 840 | "test" 841 | ], 842 | "support": { 843 | "issues": "https://github.com/hamcrest/hamcrest-php/issues", 844 | "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" 845 | }, 846 | "time": "2020-07-09T08:09:16+00:00" 847 | }, 848 | { 849 | "name": "mockery/mockery", 850 | "version": "1.5.1", 851 | "source": { 852 | "type": "git", 853 | "url": "https://github.com/mockery/mockery.git", 854 | "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e" 855 | }, 856 | "dist": { 857 | "type": "zip", 858 | "url": "https://api.github.com/repos/mockery/mockery/zipball/e92dcc83d5a51851baf5f5591d32cb2b16e3684e", 859 | "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e", 860 | "shasum": "" 861 | }, 862 | "require": { 863 | "hamcrest/hamcrest-php": "^2.0.1", 864 | "lib-pcre": ">=7.0", 865 | "php": "^7.3 || ^8.0" 866 | }, 867 | "conflict": { 868 | "phpunit/phpunit": "<8.0" 869 | }, 870 | "require-dev": { 871 | "phpunit/phpunit": "^8.5 || ^9.3" 872 | }, 873 | "type": "library", 874 | "extra": { 875 | "branch-alias": { 876 | "dev-master": "1.4.x-dev" 877 | } 878 | }, 879 | "autoload": { 880 | "psr-0": { 881 | "Mockery": "library/" 882 | } 883 | }, 884 | "notification-url": "https://packagist.org/downloads/", 885 | "license": [ 886 | "BSD-3-Clause" 887 | ], 888 | "authors": [ 889 | { 890 | "name": "Pádraic Brady", 891 | "email": "padraic.brady@gmail.com", 892 | "homepage": "http://blog.astrumfutura.com" 893 | }, 894 | { 895 | "name": "Dave Marshall", 896 | "email": "dave.marshall@atstsolutions.co.uk", 897 | "homepage": "http://davedevelopment.co.uk" 898 | } 899 | ], 900 | "description": "Mockery is a simple yet flexible PHP mock object framework", 901 | "homepage": "https://github.com/mockery/mockery", 902 | "keywords": [ 903 | "BDD", 904 | "TDD", 905 | "library", 906 | "mock", 907 | "mock objects", 908 | "mockery", 909 | "stub", 910 | "test", 911 | "test double", 912 | "testing" 913 | ], 914 | "support": { 915 | "issues": "https://github.com/mockery/mockery/issues", 916 | "source": "https://github.com/mockery/mockery/tree/1.5.1" 917 | }, 918 | "time": "2022-09-07T15:32:08+00:00" 919 | }, 920 | { 921 | "name": "myclabs/deep-copy", 922 | "version": "1.11.1", 923 | "source": { 924 | "type": "git", 925 | "url": "https://github.com/myclabs/DeepCopy.git", 926 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" 927 | }, 928 | "dist": { 929 | "type": "zip", 930 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 931 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 932 | "shasum": "" 933 | }, 934 | "require": { 935 | "php": "^7.1 || ^8.0" 936 | }, 937 | "conflict": { 938 | "doctrine/collections": "<1.6.8", 939 | "doctrine/common": "<2.13.3 || >=3,<3.2.2" 940 | }, 941 | "require-dev": { 942 | "doctrine/collections": "^1.6.8", 943 | "doctrine/common": "^2.13.3 || ^3.2.2", 944 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 945 | }, 946 | "type": "library", 947 | "autoload": { 948 | "files": [ 949 | "src/DeepCopy/deep_copy.php" 950 | ], 951 | "psr-4": { 952 | "DeepCopy\\": "src/DeepCopy/" 953 | } 954 | }, 955 | "notification-url": "https://packagist.org/downloads/", 956 | "license": [ 957 | "MIT" 958 | ], 959 | "description": "Create deep copies (clones) of your objects", 960 | "keywords": [ 961 | "clone", 962 | "copy", 963 | "duplicate", 964 | "object", 965 | "object graph" 966 | ], 967 | "support": { 968 | "issues": "https://github.com/myclabs/DeepCopy/issues", 969 | "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" 970 | }, 971 | "funding": [ 972 | { 973 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 974 | "type": "tidelift" 975 | } 976 | ], 977 | "time": "2023-03-08T13:26:56+00:00" 978 | }, 979 | { 980 | "name": "nikic/php-parser", 981 | "version": "v5.0.2", 982 | "source": { 983 | "type": "git", 984 | "url": "https://github.com/nikic/PHP-Parser.git", 985 | "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" 986 | }, 987 | "dist": { 988 | "type": "zip", 989 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", 990 | "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", 991 | "shasum": "" 992 | }, 993 | "require": { 994 | "ext-ctype": "*", 995 | "ext-json": "*", 996 | "ext-tokenizer": "*", 997 | "php": ">=7.4" 998 | }, 999 | "require-dev": { 1000 | "ircmaxell/php-yacc": "^0.0.7", 1001 | "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" 1002 | }, 1003 | "bin": [ 1004 | "bin/php-parse" 1005 | ], 1006 | "type": "library", 1007 | "extra": { 1008 | "branch-alias": { 1009 | "dev-master": "5.0-dev" 1010 | } 1011 | }, 1012 | "autoload": { 1013 | "psr-4": { 1014 | "PhpParser\\": "lib/PhpParser" 1015 | } 1016 | }, 1017 | "notification-url": "https://packagist.org/downloads/", 1018 | "license": [ 1019 | "BSD-3-Clause" 1020 | ], 1021 | "authors": [ 1022 | { 1023 | "name": "Nikita Popov" 1024 | } 1025 | ], 1026 | "description": "A PHP parser written in PHP", 1027 | "keywords": [ 1028 | "parser", 1029 | "php" 1030 | ], 1031 | "support": { 1032 | "issues": "https://github.com/nikic/PHP-Parser/issues", 1033 | "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" 1034 | }, 1035 | "time": "2024-03-05T20:51:40+00:00" 1036 | }, 1037 | { 1038 | "name": "phar-io/manifest", 1039 | "version": "2.0.4", 1040 | "source": { 1041 | "type": "git", 1042 | "url": "https://github.com/phar-io/manifest.git", 1043 | "reference": "54750ef60c58e43759730615a392c31c80e23176" 1044 | }, 1045 | "dist": { 1046 | "type": "zip", 1047 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", 1048 | "reference": "54750ef60c58e43759730615a392c31c80e23176", 1049 | "shasum": "" 1050 | }, 1051 | "require": { 1052 | "ext-dom": "*", 1053 | "ext-libxml": "*", 1054 | "ext-phar": "*", 1055 | "ext-xmlwriter": "*", 1056 | "phar-io/version": "^3.0.1", 1057 | "php": "^7.2 || ^8.0" 1058 | }, 1059 | "type": "library", 1060 | "extra": { 1061 | "branch-alias": { 1062 | "dev-master": "2.0.x-dev" 1063 | } 1064 | }, 1065 | "autoload": { 1066 | "classmap": [ 1067 | "src/" 1068 | ] 1069 | }, 1070 | "notification-url": "https://packagist.org/downloads/", 1071 | "license": [ 1072 | "BSD-3-Clause" 1073 | ], 1074 | "authors": [ 1075 | { 1076 | "name": "Arne Blankerts", 1077 | "email": "arne@blankerts.de", 1078 | "role": "Developer" 1079 | }, 1080 | { 1081 | "name": "Sebastian Heuer", 1082 | "email": "sebastian@phpeople.de", 1083 | "role": "Developer" 1084 | }, 1085 | { 1086 | "name": "Sebastian Bergmann", 1087 | "email": "sebastian@phpunit.de", 1088 | "role": "Developer" 1089 | } 1090 | ], 1091 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 1092 | "support": { 1093 | "issues": "https://github.com/phar-io/manifest/issues", 1094 | "source": "https://github.com/phar-io/manifest/tree/2.0.4" 1095 | }, 1096 | "funding": [ 1097 | { 1098 | "url": "https://github.com/theseer", 1099 | "type": "github" 1100 | } 1101 | ], 1102 | "time": "2024-03-03T12:33:53+00:00" 1103 | }, 1104 | { 1105 | "name": "phar-io/version", 1106 | "version": "3.2.1", 1107 | "source": { 1108 | "type": "git", 1109 | "url": "https://github.com/phar-io/version.git", 1110 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 1111 | }, 1112 | "dist": { 1113 | "type": "zip", 1114 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 1115 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 1116 | "shasum": "" 1117 | }, 1118 | "require": { 1119 | "php": "^7.2 || ^8.0" 1120 | }, 1121 | "type": "library", 1122 | "autoload": { 1123 | "classmap": [ 1124 | "src/" 1125 | ] 1126 | }, 1127 | "notification-url": "https://packagist.org/downloads/", 1128 | "license": [ 1129 | "BSD-3-Clause" 1130 | ], 1131 | "authors": [ 1132 | { 1133 | "name": "Arne Blankerts", 1134 | "email": "arne@blankerts.de", 1135 | "role": "Developer" 1136 | }, 1137 | { 1138 | "name": "Sebastian Heuer", 1139 | "email": "sebastian@phpeople.de", 1140 | "role": "Developer" 1141 | }, 1142 | { 1143 | "name": "Sebastian Bergmann", 1144 | "email": "sebastian@phpunit.de", 1145 | "role": "Developer" 1146 | } 1147 | ], 1148 | "description": "Library for handling version information and constraints", 1149 | "support": { 1150 | "issues": "https://github.com/phar-io/version/issues", 1151 | "source": "https://github.com/phar-io/version/tree/3.2.1" 1152 | }, 1153 | "time": "2022-02-21T01:04:05+00:00" 1154 | }, 1155 | { 1156 | "name": "phpunit/php-code-coverage", 1157 | "version": "9.2.31", 1158 | "source": { 1159 | "type": "git", 1160 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 1161 | "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" 1162 | }, 1163 | "dist": { 1164 | "type": "zip", 1165 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", 1166 | "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", 1167 | "shasum": "" 1168 | }, 1169 | "require": { 1170 | "ext-dom": "*", 1171 | "ext-libxml": "*", 1172 | "ext-xmlwriter": "*", 1173 | "nikic/php-parser": "^4.18 || ^5.0", 1174 | "php": ">=7.3", 1175 | "phpunit/php-file-iterator": "^3.0.3", 1176 | "phpunit/php-text-template": "^2.0.2", 1177 | "sebastian/code-unit-reverse-lookup": "^2.0.2", 1178 | "sebastian/complexity": "^2.0", 1179 | "sebastian/environment": "^5.1.2", 1180 | "sebastian/lines-of-code": "^1.0.3", 1181 | "sebastian/version": "^3.0.1", 1182 | "theseer/tokenizer": "^1.2.0" 1183 | }, 1184 | "require-dev": { 1185 | "phpunit/phpunit": "^9.3" 1186 | }, 1187 | "suggest": { 1188 | "ext-pcov": "PHP extension that provides line coverage", 1189 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 1190 | }, 1191 | "type": "library", 1192 | "extra": { 1193 | "branch-alias": { 1194 | "dev-master": "9.2-dev" 1195 | } 1196 | }, 1197 | "autoload": { 1198 | "classmap": [ 1199 | "src/" 1200 | ] 1201 | }, 1202 | "notification-url": "https://packagist.org/downloads/", 1203 | "license": [ 1204 | "BSD-3-Clause" 1205 | ], 1206 | "authors": [ 1207 | { 1208 | "name": "Sebastian Bergmann", 1209 | "email": "sebastian@phpunit.de", 1210 | "role": "lead" 1211 | } 1212 | ], 1213 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1214 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1215 | "keywords": [ 1216 | "coverage", 1217 | "testing", 1218 | "xunit" 1219 | ], 1220 | "support": { 1221 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 1222 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 1223 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" 1224 | }, 1225 | "funding": [ 1226 | { 1227 | "url": "https://github.com/sebastianbergmann", 1228 | "type": "github" 1229 | } 1230 | ], 1231 | "time": "2024-03-02T06:37:42+00:00" 1232 | }, 1233 | { 1234 | "name": "phpunit/php-file-iterator", 1235 | "version": "3.0.6", 1236 | "source": { 1237 | "type": "git", 1238 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1239 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" 1240 | }, 1241 | "dist": { 1242 | "type": "zip", 1243 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 1244 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 1245 | "shasum": "" 1246 | }, 1247 | "require": { 1248 | "php": ">=7.3" 1249 | }, 1250 | "require-dev": { 1251 | "phpunit/phpunit": "^9.3" 1252 | }, 1253 | "type": "library", 1254 | "extra": { 1255 | "branch-alias": { 1256 | "dev-master": "3.0-dev" 1257 | } 1258 | }, 1259 | "autoload": { 1260 | "classmap": [ 1261 | "src/" 1262 | ] 1263 | }, 1264 | "notification-url": "https://packagist.org/downloads/", 1265 | "license": [ 1266 | "BSD-3-Clause" 1267 | ], 1268 | "authors": [ 1269 | { 1270 | "name": "Sebastian Bergmann", 1271 | "email": "sebastian@phpunit.de", 1272 | "role": "lead" 1273 | } 1274 | ], 1275 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1276 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1277 | "keywords": [ 1278 | "filesystem", 1279 | "iterator" 1280 | ], 1281 | "support": { 1282 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 1283 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" 1284 | }, 1285 | "funding": [ 1286 | { 1287 | "url": "https://github.com/sebastianbergmann", 1288 | "type": "github" 1289 | } 1290 | ], 1291 | "time": "2021-12-02T12:48:52+00:00" 1292 | }, 1293 | { 1294 | "name": "phpunit/php-invoker", 1295 | "version": "3.1.1", 1296 | "source": { 1297 | "type": "git", 1298 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 1299 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" 1300 | }, 1301 | "dist": { 1302 | "type": "zip", 1303 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 1304 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 1305 | "shasum": "" 1306 | }, 1307 | "require": { 1308 | "php": ">=7.3" 1309 | }, 1310 | "require-dev": { 1311 | "ext-pcntl": "*", 1312 | "phpunit/phpunit": "^9.3" 1313 | }, 1314 | "suggest": { 1315 | "ext-pcntl": "*" 1316 | }, 1317 | "type": "library", 1318 | "extra": { 1319 | "branch-alias": { 1320 | "dev-master": "3.1-dev" 1321 | } 1322 | }, 1323 | "autoload": { 1324 | "classmap": [ 1325 | "src/" 1326 | ] 1327 | }, 1328 | "notification-url": "https://packagist.org/downloads/", 1329 | "license": [ 1330 | "BSD-3-Clause" 1331 | ], 1332 | "authors": [ 1333 | { 1334 | "name": "Sebastian Bergmann", 1335 | "email": "sebastian@phpunit.de", 1336 | "role": "lead" 1337 | } 1338 | ], 1339 | "description": "Invoke callables with a timeout", 1340 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 1341 | "keywords": [ 1342 | "process" 1343 | ], 1344 | "support": { 1345 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 1346 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" 1347 | }, 1348 | "funding": [ 1349 | { 1350 | "url": "https://github.com/sebastianbergmann", 1351 | "type": "github" 1352 | } 1353 | ], 1354 | "time": "2020-09-28T05:58:55+00:00" 1355 | }, 1356 | { 1357 | "name": "phpunit/php-text-template", 1358 | "version": "2.0.4", 1359 | "source": { 1360 | "type": "git", 1361 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1362 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" 1363 | }, 1364 | "dist": { 1365 | "type": "zip", 1366 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 1367 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 1368 | "shasum": "" 1369 | }, 1370 | "require": { 1371 | "php": ">=7.3" 1372 | }, 1373 | "require-dev": { 1374 | "phpunit/phpunit": "^9.3" 1375 | }, 1376 | "type": "library", 1377 | "extra": { 1378 | "branch-alias": { 1379 | "dev-master": "2.0-dev" 1380 | } 1381 | }, 1382 | "autoload": { 1383 | "classmap": [ 1384 | "src/" 1385 | ] 1386 | }, 1387 | "notification-url": "https://packagist.org/downloads/", 1388 | "license": [ 1389 | "BSD-3-Clause" 1390 | ], 1391 | "authors": [ 1392 | { 1393 | "name": "Sebastian Bergmann", 1394 | "email": "sebastian@phpunit.de", 1395 | "role": "lead" 1396 | } 1397 | ], 1398 | "description": "Simple template engine.", 1399 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1400 | "keywords": [ 1401 | "template" 1402 | ], 1403 | "support": { 1404 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 1405 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" 1406 | }, 1407 | "funding": [ 1408 | { 1409 | "url": "https://github.com/sebastianbergmann", 1410 | "type": "github" 1411 | } 1412 | ], 1413 | "time": "2020-10-26T05:33:50+00:00" 1414 | }, 1415 | { 1416 | "name": "phpunit/php-timer", 1417 | "version": "5.0.3", 1418 | "source": { 1419 | "type": "git", 1420 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1421 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" 1422 | }, 1423 | "dist": { 1424 | "type": "zip", 1425 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 1426 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 1427 | "shasum": "" 1428 | }, 1429 | "require": { 1430 | "php": ">=7.3" 1431 | }, 1432 | "require-dev": { 1433 | "phpunit/phpunit": "^9.3" 1434 | }, 1435 | "type": "library", 1436 | "extra": { 1437 | "branch-alias": { 1438 | "dev-master": "5.0-dev" 1439 | } 1440 | }, 1441 | "autoload": { 1442 | "classmap": [ 1443 | "src/" 1444 | ] 1445 | }, 1446 | "notification-url": "https://packagist.org/downloads/", 1447 | "license": [ 1448 | "BSD-3-Clause" 1449 | ], 1450 | "authors": [ 1451 | { 1452 | "name": "Sebastian Bergmann", 1453 | "email": "sebastian@phpunit.de", 1454 | "role": "lead" 1455 | } 1456 | ], 1457 | "description": "Utility class for timing", 1458 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1459 | "keywords": [ 1460 | "timer" 1461 | ], 1462 | "support": { 1463 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 1464 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" 1465 | }, 1466 | "funding": [ 1467 | { 1468 | "url": "https://github.com/sebastianbergmann", 1469 | "type": "github" 1470 | } 1471 | ], 1472 | "time": "2020-10-26T13:16:10+00:00" 1473 | }, 1474 | { 1475 | "name": "phpunit/phpunit", 1476 | "version": "9.6.17", 1477 | "source": { 1478 | "type": "git", 1479 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1480 | "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd" 1481 | }, 1482 | "dist": { 1483 | "type": "zip", 1484 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd", 1485 | "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd", 1486 | "shasum": "" 1487 | }, 1488 | "require": { 1489 | "doctrine/instantiator": "^1.3.1 || ^2", 1490 | "ext-dom": "*", 1491 | "ext-json": "*", 1492 | "ext-libxml": "*", 1493 | "ext-mbstring": "*", 1494 | "ext-xml": "*", 1495 | "ext-xmlwriter": "*", 1496 | "myclabs/deep-copy": "^1.10.1", 1497 | "phar-io/manifest": "^2.0.3", 1498 | "phar-io/version": "^3.0.2", 1499 | "php": ">=7.3", 1500 | "phpunit/php-code-coverage": "^9.2.28", 1501 | "phpunit/php-file-iterator": "^3.0.5", 1502 | "phpunit/php-invoker": "^3.1.1", 1503 | "phpunit/php-text-template": "^2.0.3", 1504 | "phpunit/php-timer": "^5.0.2", 1505 | "sebastian/cli-parser": "^1.0.1", 1506 | "sebastian/code-unit": "^1.0.6", 1507 | "sebastian/comparator": "^4.0.8", 1508 | "sebastian/diff": "^4.0.3", 1509 | "sebastian/environment": "^5.1.3", 1510 | "sebastian/exporter": "^4.0.5", 1511 | "sebastian/global-state": "^5.0.1", 1512 | "sebastian/object-enumerator": "^4.0.3", 1513 | "sebastian/resource-operations": "^3.0.3", 1514 | "sebastian/type": "^3.2", 1515 | "sebastian/version": "^3.0.2" 1516 | }, 1517 | "suggest": { 1518 | "ext-soap": "To be able to generate mocks based on WSDL files", 1519 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 1520 | }, 1521 | "bin": [ 1522 | "phpunit" 1523 | ], 1524 | "type": "library", 1525 | "extra": { 1526 | "branch-alias": { 1527 | "dev-master": "9.6-dev" 1528 | } 1529 | }, 1530 | "autoload": { 1531 | "files": [ 1532 | "src/Framework/Assert/Functions.php" 1533 | ], 1534 | "classmap": [ 1535 | "src/" 1536 | ] 1537 | }, 1538 | "notification-url": "https://packagist.org/downloads/", 1539 | "license": [ 1540 | "BSD-3-Clause" 1541 | ], 1542 | "authors": [ 1543 | { 1544 | "name": "Sebastian Bergmann", 1545 | "email": "sebastian@phpunit.de", 1546 | "role": "lead" 1547 | } 1548 | ], 1549 | "description": "The PHP Unit Testing framework.", 1550 | "homepage": "https://phpunit.de/", 1551 | "keywords": [ 1552 | "phpunit", 1553 | "testing", 1554 | "xunit" 1555 | ], 1556 | "support": { 1557 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 1558 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 1559 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17" 1560 | }, 1561 | "funding": [ 1562 | { 1563 | "url": "https://phpunit.de/sponsors.html", 1564 | "type": "custom" 1565 | }, 1566 | { 1567 | "url": "https://github.com/sebastianbergmann", 1568 | "type": "github" 1569 | }, 1570 | { 1571 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 1572 | "type": "tidelift" 1573 | } 1574 | ], 1575 | "time": "2024-02-23T13:14:51+00:00" 1576 | }, 1577 | { 1578 | "name": "sebastian/cli-parser", 1579 | "version": "1.0.2", 1580 | "source": { 1581 | "type": "git", 1582 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 1583 | "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" 1584 | }, 1585 | "dist": { 1586 | "type": "zip", 1587 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", 1588 | "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", 1589 | "shasum": "" 1590 | }, 1591 | "require": { 1592 | "php": ">=7.3" 1593 | }, 1594 | "require-dev": { 1595 | "phpunit/phpunit": "^9.3" 1596 | }, 1597 | "type": "library", 1598 | "extra": { 1599 | "branch-alias": { 1600 | "dev-master": "1.0-dev" 1601 | } 1602 | }, 1603 | "autoload": { 1604 | "classmap": [ 1605 | "src/" 1606 | ] 1607 | }, 1608 | "notification-url": "https://packagist.org/downloads/", 1609 | "license": [ 1610 | "BSD-3-Clause" 1611 | ], 1612 | "authors": [ 1613 | { 1614 | "name": "Sebastian Bergmann", 1615 | "email": "sebastian@phpunit.de", 1616 | "role": "lead" 1617 | } 1618 | ], 1619 | "description": "Library for parsing CLI options", 1620 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 1621 | "support": { 1622 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 1623 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" 1624 | }, 1625 | "funding": [ 1626 | { 1627 | "url": "https://github.com/sebastianbergmann", 1628 | "type": "github" 1629 | } 1630 | ], 1631 | "time": "2024-03-02T06:27:43+00:00" 1632 | }, 1633 | { 1634 | "name": "sebastian/code-unit", 1635 | "version": "1.0.8", 1636 | "source": { 1637 | "type": "git", 1638 | "url": "https://github.com/sebastianbergmann/code-unit.git", 1639 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" 1640 | }, 1641 | "dist": { 1642 | "type": "zip", 1643 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", 1644 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", 1645 | "shasum": "" 1646 | }, 1647 | "require": { 1648 | "php": ">=7.3" 1649 | }, 1650 | "require-dev": { 1651 | "phpunit/phpunit": "^9.3" 1652 | }, 1653 | "type": "library", 1654 | "extra": { 1655 | "branch-alias": { 1656 | "dev-master": "1.0-dev" 1657 | } 1658 | }, 1659 | "autoload": { 1660 | "classmap": [ 1661 | "src/" 1662 | ] 1663 | }, 1664 | "notification-url": "https://packagist.org/downloads/", 1665 | "license": [ 1666 | "BSD-3-Clause" 1667 | ], 1668 | "authors": [ 1669 | { 1670 | "name": "Sebastian Bergmann", 1671 | "email": "sebastian@phpunit.de", 1672 | "role": "lead" 1673 | } 1674 | ], 1675 | "description": "Collection of value objects that represent the PHP code units", 1676 | "homepage": "https://github.com/sebastianbergmann/code-unit", 1677 | "support": { 1678 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 1679 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" 1680 | }, 1681 | "funding": [ 1682 | { 1683 | "url": "https://github.com/sebastianbergmann", 1684 | "type": "github" 1685 | } 1686 | ], 1687 | "time": "2020-10-26T13:08:54+00:00" 1688 | }, 1689 | { 1690 | "name": "sebastian/code-unit-reverse-lookup", 1691 | "version": "2.0.3", 1692 | "source": { 1693 | "type": "git", 1694 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1695 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" 1696 | }, 1697 | "dist": { 1698 | "type": "zip", 1699 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1700 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1701 | "shasum": "" 1702 | }, 1703 | "require": { 1704 | "php": ">=7.3" 1705 | }, 1706 | "require-dev": { 1707 | "phpunit/phpunit": "^9.3" 1708 | }, 1709 | "type": "library", 1710 | "extra": { 1711 | "branch-alias": { 1712 | "dev-master": "2.0-dev" 1713 | } 1714 | }, 1715 | "autoload": { 1716 | "classmap": [ 1717 | "src/" 1718 | ] 1719 | }, 1720 | "notification-url": "https://packagist.org/downloads/", 1721 | "license": [ 1722 | "BSD-3-Clause" 1723 | ], 1724 | "authors": [ 1725 | { 1726 | "name": "Sebastian Bergmann", 1727 | "email": "sebastian@phpunit.de" 1728 | } 1729 | ], 1730 | "description": "Looks up which function or method a line of code belongs to", 1731 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1732 | "support": { 1733 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 1734 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" 1735 | }, 1736 | "funding": [ 1737 | { 1738 | "url": "https://github.com/sebastianbergmann", 1739 | "type": "github" 1740 | } 1741 | ], 1742 | "time": "2020-09-28T05:30:19+00:00" 1743 | }, 1744 | { 1745 | "name": "sebastian/comparator", 1746 | "version": "4.0.8", 1747 | "source": { 1748 | "type": "git", 1749 | "url": "https://github.com/sebastianbergmann/comparator.git", 1750 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a" 1751 | }, 1752 | "dist": { 1753 | "type": "zip", 1754 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", 1755 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a", 1756 | "shasum": "" 1757 | }, 1758 | "require": { 1759 | "php": ">=7.3", 1760 | "sebastian/diff": "^4.0", 1761 | "sebastian/exporter": "^4.0" 1762 | }, 1763 | "require-dev": { 1764 | "phpunit/phpunit": "^9.3" 1765 | }, 1766 | "type": "library", 1767 | "extra": { 1768 | "branch-alias": { 1769 | "dev-master": "4.0-dev" 1770 | } 1771 | }, 1772 | "autoload": { 1773 | "classmap": [ 1774 | "src/" 1775 | ] 1776 | }, 1777 | "notification-url": "https://packagist.org/downloads/", 1778 | "license": [ 1779 | "BSD-3-Clause" 1780 | ], 1781 | "authors": [ 1782 | { 1783 | "name": "Sebastian Bergmann", 1784 | "email": "sebastian@phpunit.de" 1785 | }, 1786 | { 1787 | "name": "Jeff Welch", 1788 | "email": "whatthejeff@gmail.com" 1789 | }, 1790 | { 1791 | "name": "Volker Dusch", 1792 | "email": "github@wallbash.com" 1793 | }, 1794 | { 1795 | "name": "Bernhard Schussek", 1796 | "email": "bschussek@2bepublished.at" 1797 | } 1798 | ], 1799 | "description": "Provides the functionality to compare PHP values for equality", 1800 | "homepage": "https://github.com/sebastianbergmann/comparator", 1801 | "keywords": [ 1802 | "comparator", 1803 | "compare", 1804 | "equality" 1805 | ], 1806 | "support": { 1807 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1808 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" 1809 | }, 1810 | "funding": [ 1811 | { 1812 | "url": "https://github.com/sebastianbergmann", 1813 | "type": "github" 1814 | } 1815 | ], 1816 | "time": "2022-09-14T12:41:17+00:00" 1817 | }, 1818 | { 1819 | "name": "sebastian/complexity", 1820 | "version": "2.0.3", 1821 | "source": { 1822 | "type": "git", 1823 | "url": "https://github.com/sebastianbergmann/complexity.git", 1824 | "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" 1825 | }, 1826 | "dist": { 1827 | "type": "zip", 1828 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", 1829 | "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", 1830 | "shasum": "" 1831 | }, 1832 | "require": { 1833 | "nikic/php-parser": "^4.18 || ^5.0", 1834 | "php": ">=7.3" 1835 | }, 1836 | "require-dev": { 1837 | "phpunit/phpunit": "^9.3" 1838 | }, 1839 | "type": "library", 1840 | "extra": { 1841 | "branch-alias": { 1842 | "dev-master": "2.0-dev" 1843 | } 1844 | }, 1845 | "autoload": { 1846 | "classmap": [ 1847 | "src/" 1848 | ] 1849 | }, 1850 | "notification-url": "https://packagist.org/downloads/", 1851 | "license": [ 1852 | "BSD-3-Clause" 1853 | ], 1854 | "authors": [ 1855 | { 1856 | "name": "Sebastian Bergmann", 1857 | "email": "sebastian@phpunit.de", 1858 | "role": "lead" 1859 | } 1860 | ], 1861 | "description": "Library for calculating the complexity of PHP code units", 1862 | "homepage": "https://github.com/sebastianbergmann/complexity", 1863 | "support": { 1864 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1865 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" 1866 | }, 1867 | "funding": [ 1868 | { 1869 | "url": "https://github.com/sebastianbergmann", 1870 | "type": "github" 1871 | } 1872 | ], 1873 | "time": "2023-12-22T06:19:30+00:00" 1874 | }, 1875 | { 1876 | "name": "sebastian/diff", 1877 | "version": "4.0.6", 1878 | "source": { 1879 | "type": "git", 1880 | "url": "https://github.com/sebastianbergmann/diff.git", 1881 | "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" 1882 | }, 1883 | "dist": { 1884 | "type": "zip", 1885 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", 1886 | "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", 1887 | "shasum": "" 1888 | }, 1889 | "require": { 1890 | "php": ">=7.3" 1891 | }, 1892 | "require-dev": { 1893 | "phpunit/phpunit": "^9.3", 1894 | "symfony/process": "^4.2 || ^5" 1895 | }, 1896 | "type": "library", 1897 | "extra": { 1898 | "branch-alias": { 1899 | "dev-master": "4.0-dev" 1900 | } 1901 | }, 1902 | "autoload": { 1903 | "classmap": [ 1904 | "src/" 1905 | ] 1906 | }, 1907 | "notification-url": "https://packagist.org/downloads/", 1908 | "license": [ 1909 | "BSD-3-Clause" 1910 | ], 1911 | "authors": [ 1912 | { 1913 | "name": "Sebastian Bergmann", 1914 | "email": "sebastian@phpunit.de" 1915 | }, 1916 | { 1917 | "name": "Kore Nordmann", 1918 | "email": "mail@kore-nordmann.de" 1919 | } 1920 | ], 1921 | "description": "Diff implementation", 1922 | "homepage": "https://github.com/sebastianbergmann/diff", 1923 | "keywords": [ 1924 | "diff", 1925 | "udiff", 1926 | "unidiff", 1927 | "unified diff" 1928 | ], 1929 | "support": { 1930 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1931 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" 1932 | }, 1933 | "funding": [ 1934 | { 1935 | "url": "https://github.com/sebastianbergmann", 1936 | "type": "github" 1937 | } 1938 | ], 1939 | "time": "2024-03-02T06:30:58+00:00" 1940 | }, 1941 | { 1942 | "name": "sebastian/environment", 1943 | "version": "5.1.5", 1944 | "source": { 1945 | "type": "git", 1946 | "url": "https://github.com/sebastianbergmann/environment.git", 1947 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" 1948 | }, 1949 | "dist": { 1950 | "type": "zip", 1951 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1952 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1953 | "shasum": "" 1954 | }, 1955 | "require": { 1956 | "php": ">=7.3" 1957 | }, 1958 | "require-dev": { 1959 | "phpunit/phpunit": "^9.3" 1960 | }, 1961 | "suggest": { 1962 | "ext-posix": "*" 1963 | }, 1964 | "type": "library", 1965 | "extra": { 1966 | "branch-alias": { 1967 | "dev-master": "5.1-dev" 1968 | } 1969 | }, 1970 | "autoload": { 1971 | "classmap": [ 1972 | "src/" 1973 | ] 1974 | }, 1975 | "notification-url": "https://packagist.org/downloads/", 1976 | "license": [ 1977 | "BSD-3-Clause" 1978 | ], 1979 | "authors": [ 1980 | { 1981 | "name": "Sebastian Bergmann", 1982 | "email": "sebastian@phpunit.de" 1983 | } 1984 | ], 1985 | "description": "Provides functionality to handle HHVM/PHP environments", 1986 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1987 | "keywords": [ 1988 | "Xdebug", 1989 | "environment", 1990 | "hhvm" 1991 | ], 1992 | "support": { 1993 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1994 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" 1995 | }, 1996 | "funding": [ 1997 | { 1998 | "url": "https://github.com/sebastianbergmann", 1999 | "type": "github" 2000 | } 2001 | ], 2002 | "time": "2023-02-03T06:03:51+00:00" 2003 | }, 2004 | { 2005 | "name": "sebastian/exporter", 2006 | "version": "4.0.6", 2007 | "source": { 2008 | "type": "git", 2009 | "url": "https://github.com/sebastianbergmann/exporter.git", 2010 | "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" 2011 | }, 2012 | "dist": { 2013 | "type": "zip", 2014 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", 2015 | "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", 2016 | "shasum": "" 2017 | }, 2018 | "require": { 2019 | "php": ">=7.3", 2020 | "sebastian/recursion-context": "^4.0" 2021 | }, 2022 | "require-dev": { 2023 | "ext-mbstring": "*", 2024 | "phpunit/phpunit": "^9.3" 2025 | }, 2026 | "type": "library", 2027 | "extra": { 2028 | "branch-alias": { 2029 | "dev-master": "4.0-dev" 2030 | } 2031 | }, 2032 | "autoload": { 2033 | "classmap": [ 2034 | "src/" 2035 | ] 2036 | }, 2037 | "notification-url": "https://packagist.org/downloads/", 2038 | "license": [ 2039 | "BSD-3-Clause" 2040 | ], 2041 | "authors": [ 2042 | { 2043 | "name": "Sebastian Bergmann", 2044 | "email": "sebastian@phpunit.de" 2045 | }, 2046 | { 2047 | "name": "Jeff Welch", 2048 | "email": "whatthejeff@gmail.com" 2049 | }, 2050 | { 2051 | "name": "Volker Dusch", 2052 | "email": "github@wallbash.com" 2053 | }, 2054 | { 2055 | "name": "Adam Harvey", 2056 | "email": "aharvey@php.net" 2057 | }, 2058 | { 2059 | "name": "Bernhard Schussek", 2060 | "email": "bschussek@gmail.com" 2061 | } 2062 | ], 2063 | "description": "Provides the functionality to export PHP variables for visualization", 2064 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 2065 | "keywords": [ 2066 | "export", 2067 | "exporter" 2068 | ], 2069 | "support": { 2070 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 2071 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" 2072 | }, 2073 | "funding": [ 2074 | { 2075 | "url": "https://github.com/sebastianbergmann", 2076 | "type": "github" 2077 | } 2078 | ], 2079 | "time": "2024-03-02T06:33:00+00:00" 2080 | }, 2081 | { 2082 | "name": "sebastian/global-state", 2083 | "version": "5.0.7", 2084 | "source": { 2085 | "type": "git", 2086 | "url": "https://github.com/sebastianbergmann/global-state.git", 2087 | "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" 2088 | }, 2089 | "dist": { 2090 | "type": "zip", 2091 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", 2092 | "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", 2093 | "shasum": "" 2094 | }, 2095 | "require": { 2096 | "php": ">=7.3", 2097 | "sebastian/object-reflector": "^2.0", 2098 | "sebastian/recursion-context": "^4.0" 2099 | }, 2100 | "require-dev": { 2101 | "ext-dom": "*", 2102 | "phpunit/phpunit": "^9.3" 2103 | }, 2104 | "suggest": { 2105 | "ext-uopz": "*" 2106 | }, 2107 | "type": "library", 2108 | "extra": { 2109 | "branch-alias": { 2110 | "dev-master": "5.0-dev" 2111 | } 2112 | }, 2113 | "autoload": { 2114 | "classmap": [ 2115 | "src/" 2116 | ] 2117 | }, 2118 | "notification-url": "https://packagist.org/downloads/", 2119 | "license": [ 2120 | "BSD-3-Clause" 2121 | ], 2122 | "authors": [ 2123 | { 2124 | "name": "Sebastian Bergmann", 2125 | "email": "sebastian@phpunit.de" 2126 | } 2127 | ], 2128 | "description": "Snapshotting of global state", 2129 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 2130 | "keywords": [ 2131 | "global state" 2132 | ], 2133 | "support": { 2134 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 2135 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" 2136 | }, 2137 | "funding": [ 2138 | { 2139 | "url": "https://github.com/sebastianbergmann", 2140 | "type": "github" 2141 | } 2142 | ], 2143 | "time": "2024-03-02T06:35:11+00:00" 2144 | }, 2145 | { 2146 | "name": "sebastian/lines-of-code", 2147 | "version": "1.0.4", 2148 | "source": { 2149 | "type": "git", 2150 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 2151 | "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" 2152 | }, 2153 | "dist": { 2154 | "type": "zip", 2155 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", 2156 | "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", 2157 | "shasum": "" 2158 | }, 2159 | "require": { 2160 | "nikic/php-parser": "^4.18 || ^5.0", 2161 | "php": ">=7.3" 2162 | }, 2163 | "require-dev": { 2164 | "phpunit/phpunit": "^9.3" 2165 | }, 2166 | "type": "library", 2167 | "extra": { 2168 | "branch-alias": { 2169 | "dev-master": "1.0-dev" 2170 | } 2171 | }, 2172 | "autoload": { 2173 | "classmap": [ 2174 | "src/" 2175 | ] 2176 | }, 2177 | "notification-url": "https://packagist.org/downloads/", 2178 | "license": [ 2179 | "BSD-3-Clause" 2180 | ], 2181 | "authors": [ 2182 | { 2183 | "name": "Sebastian Bergmann", 2184 | "email": "sebastian@phpunit.de", 2185 | "role": "lead" 2186 | } 2187 | ], 2188 | "description": "Library for counting the lines of code in PHP source code", 2189 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 2190 | "support": { 2191 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 2192 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" 2193 | }, 2194 | "funding": [ 2195 | { 2196 | "url": "https://github.com/sebastianbergmann", 2197 | "type": "github" 2198 | } 2199 | ], 2200 | "time": "2023-12-22T06:20:34+00:00" 2201 | }, 2202 | { 2203 | "name": "sebastian/object-enumerator", 2204 | "version": "4.0.4", 2205 | "source": { 2206 | "type": "git", 2207 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 2208 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" 2209 | }, 2210 | "dist": { 2211 | "type": "zip", 2212 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", 2213 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", 2214 | "shasum": "" 2215 | }, 2216 | "require": { 2217 | "php": ">=7.3", 2218 | "sebastian/object-reflector": "^2.0", 2219 | "sebastian/recursion-context": "^4.0" 2220 | }, 2221 | "require-dev": { 2222 | "phpunit/phpunit": "^9.3" 2223 | }, 2224 | "type": "library", 2225 | "extra": { 2226 | "branch-alias": { 2227 | "dev-master": "4.0-dev" 2228 | } 2229 | }, 2230 | "autoload": { 2231 | "classmap": [ 2232 | "src/" 2233 | ] 2234 | }, 2235 | "notification-url": "https://packagist.org/downloads/", 2236 | "license": [ 2237 | "BSD-3-Clause" 2238 | ], 2239 | "authors": [ 2240 | { 2241 | "name": "Sebastian Bergmann", 2242 | "email": "sebastian@phpunit.de" 2243 | } 2244 | ], 2245 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 2246 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 2247 | "support": { 2248 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 2249 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" 2250 | }, 2251 | "funding": [ 2252 | { 2253 | "url": "https://github.com/sebastianbergmann", 2254 | "type": "github" 2255 | } 2256 | ], 2257 | "time": "2020-10-26T13:12:34+00:00" 2258 | }, 2259 | { 2260 | "name": "sebastian/object-reflector", 2261 | "version": "2.0.4", 2262 | "source": { 2263 | "type": "git", 2264 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 2265 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" 2266 | }, 2267 | "dist": { 2268 | "type": "zip", 2269 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 2270 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 2271 | "shasum": "" 2272 | }, 2273 | "require": { 2274 | "php": ">=7.3" 2275 | }, 2276 | "require-dev": { 2277 | "phpunit/phpunit": "^9.3" 2278 | }, 2279 | "type": "library", 2280 | "extra": { 2281 | "branch-alias": { 2282 | "dev-master": "2.0-dev" 2283 | } 2284 | }, 2285 | "autoload": { 2286 | "classmap": [ 2287 | "src/" 2288 | ] 2289 | }, 2290 | "notification-url": "https://packagist.org/downloads/", 2291 | "license": [ 2292 | "BSD-3-Clause" 2293 | ], 2294 | "authors": [ 2295 | { 2296 | "name": "Sebastian Bergmann", 2297 | "email": "sebastian@phpunit.de" 2298 | } 2299 | ], 2300 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 2301 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 2302 | "support": { 2303 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 2304 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" 2305 | }, 2306 | "funding": [ 2307 | { 2308 | "url": "https://github.com/sebastianbergmann", 2309 | "type": "github" 2310 | } 2311 | ], 2312 | "time": "2020-10-26T13:14:26+00:00" 2313 | }, 2314 | { 2315 | "name": "sebastian/recursion-context", 2316 | "version": "4.0.5", 2317 | "source": { 2318 | "type": "git", 2319 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 2320 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" 2321 | }, 2322 | "dist": { 2323 | "type": "zip", 2324 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 2325 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 2326 | "shasum": "" 2327 | }, 2328 | "require": { 2329 | "php": ">=7.3" 2330 | }, 2331 | "require-dev": { 2332 | "phpunit/phpunit": "^9.3" 2333 | }, 2334 | "type": "library", 2335 | "extra": { 2336 | "branch-alias": { 2337 | "dev-master": "4.0-dev" 2338 | } 2339 | }, 2340 | "autoload": { 2341 | "classmap": [ 2342 | "src/" 2343 | ] 2344 | }, 2345 | "notification-url": "https://packagist.org/downloads/", 2346 | "license": [ 2347 | "BSD-3-Clause" 2348 | ], 2349 | "authors": [ 2350 | { 2351 | "name": "Sebastian Bergmann", 2352 | "email": "sebastian@phpunit.de" 2353 | }, 2354 | { 2355 | "name": "Jeff Welch", 2356 | "email": "whatthejeff@gmail.com" 2357 | }, 2358 | { 2359 | "name": "Adam Harvey", 2360 | "email": "aharvey@php.net" 2361 | } 2362 | ], 2363 | "description": "Provides functionality to recursively process PHP variables", 2364 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 2365 | "support": { 2366 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 2367 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" 2368 | }, 2369 | "funding": [ 2370 | { 2371 | "url": "https://github.com/sebastianbergmann", 2372 | "type": "github" 2373 | } 2374 | ], 2375 | "time": "2023-02-03T06:07:39+00:00" 2376 | }, 2377 | { 2378 | "name": "sebastian/resource-operations", 2379 | "version": "3.0.3", 2380 | "source": { 2381 | "type": "git", 2382 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 2383 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" 2384 | }, 2385 | "dist": { 2386 | "type": "zip", 2387 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 2388 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 2389 | "shasum": "" 2390 | }, 2391 | "require": { 2392 | "php": ">=7.3" 2393 | }, 2394 | "require-dev": { 2395 | "phpunit/phpunit": "^9.0" 2396 | }, 2397 | "type": "library", 2398 | "extra": { 2399 | "branch-alias": { 2400 | "dev-master": "3.0-dev" 2401 | } 2402 | }, 2403 | "autoload": { 2404 | "classmap": [ 2405 | "src/" 2406 | ] 2407 | }, 2408 | "notification-url": "https://packagist.org/downloads/", 2409 | "license": [ 2410 | "BSD-3-Clause" 2411 | ], 2412 | "authors": [ 2413 | { 2414 | "name": "Sebastian Bergmann", 2415 | "email": "sebastian@phpunit.de" 2416 | } 2417 | ], 2418 | "description": "Provides a list of PHP built-in functions that operate on resources", 2419 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 2420 | "support": { 2421 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues", 2422 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" 2423 | }, 2424 | "funding": [ 2425 | { 2426 | "url": "https://github.com/sebastianbergmann", 2427 | "type": "github" 2428 | } 2429 | ], 2430 | "time": "2020-09-28T06:45:17+00:00" 2431 | }, 2432 | { 2433 | "name": "sebastian/type", 2434 | "version": "3.2.1", 2435 | "source": { 2436 | "type": "git", 2437 | "url": "https://github.com/sebastianbergmann/type.git", 2438 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" 2439 | }, 2440 | "dist": { 2441 | "type": "zip", 2442 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 2443 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 2444 | "shasum": "" 2445 | }, 2446 | "require": { 2447 | "php": ">=7.3" 2448 | }, 2449 | "require-dev": { 2450 | "phpunit/phpunit": "^9.5" 2451 | }, 2452 | "type": "library", 2453 | "extra": { 2454 | "branch-alias": { 2455 | "dev-master": "3.2-dev" 2456 | } 2457 | }, 2458 | "autoload": { 2459 | "classmap": [ 2460 | "src/" 2461 | ] 2462 | }, 2463 | "notification-url": "https://packagist.org/downloads/", 2464 | "license": [ 2465 | "BSD-3-Clause" 2466 | ], 2467 | "authors": [ 2468 | { 2469 | "name": "Sebastian Bergmann", 2470 | "email": "sebastian@phpunit.de", 2471 | "role": "lead" 2472 | } 2473 | ], 2474 | "description": "Collection of value objects that represent the types of the PHP type system", 2475 | "homepage": "https://github.com/sebastianbergmann/type", 2476 | "support": { 2477 | "issues": "https://github.com/sebastianbergmann/type/issues", 2478 | "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" 2479 | }, 2480 | "funding": [ 2481 | { 2482 | "url": "https://github.com/sebastianbergmann", 2483 | "type": "github" 2484 | } 2485 | ], 2486 | "time": "2023-02-03T06:13:03+00:00" 2487 | }, 2488 | { 2489 | "name": "sebastian/version", 2490 | "version": "3.0.2", 2491 | "source": { 2492 | "type": "git", 2493 | "url": "https://github.com/sebastianbergmann/version.git", 2494 | "reference": "c6c1022351a901512170118436c764e473f6de8c" 2495 | }, 2496 | "dist": { 2497 | "type": "zip", 2498 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", 2499 | "reference": "c6c1022351a901512170118436c764e473f6de8c", 2500 | "shasum": "" 2501 | }, 2502 | "require": { 2503 | "php": ">=7.3" 2504 | }, 2505 | "type": "library", 2506 | "extra": { 2507 | "branch-alias": { 2508 | "dev-master": "3.0-dev" 2509 | } 2510 | }, 2511 | "autoload": { 2512 | "classmap": [ 2513 | "src/" 2514 | ] 2515 | }, 2516 | "notification-url": "https://packagist.org/downloads/", 2517 | "license": [ 2518 | "BSD-3-Clause" 2519 | ], 2520 | "authors": [ 2521 | { 2522 | "name": "Sebastian Bergmann", 2523 | "email": "sebastian@phpunit.de", 2524 | "role": "lead" 2525 | } 2526 | ], 2527 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2528 | "homepage": "https://github.com/sebastianbergmann/version", 2529 | "support": { 2530 | "issues": "https://github.com/sebastianbergmann/version/issues", 2531 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" 2532 | }, 2533 | "funding": [ 2534 | { 2535 | "url": "https://github.com/sebastianbergmann", 2536 | "type": "github" 2537 | } 2538 | ], 2539 | "time": "2020-09-28T06:39:44+00:00" 2540 | }, 2541 | { 2542 | "name": "theseer/tokenizer", 2543 | "version": "1.2.3", 2544 | "source": { 2545 | "type": "git", 2546 | "url": "https://github.com/theseer/tokenizer.git", 2547 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" 2548 | }, 2549 | "dist": { 2550 | "type": "zip", 2551 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 2552 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 2553 | "shasum": "" 2554 | }, 2555 | "require": { 2556 | "ext-dom": "*", 2557 | "ext-tokenizer": "*", 2558 | "ext-xmlwriter": "*", 2559 | "php": "^7.2 || ^8.0" 2560 | }, 2561 | "type": "library", 2562 | "autoload": { 2563 | "classmap": [ 2564 | "src/" 2565 | ] 2566 | }, 2567 | "notification-url": "https://packagist.org/downloads/", 2568 | "license": [ 2569 | "BSD-3-Clause" 2570 | ], 2571 | "authors": [ 2572 | { 2573 | "name": "Arne Blankerts", 2574 | "email": "arne@blankerts.de", 2575 | "role": "Developer" 2576 | } 2577 | ], 2578 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2579 | "support": { 2580 | "issues": "https://github.com/theseer/tokenizer/issues", 2581 | "source": "https://github.com/theseer/tokenizer/tree/1.2.3" 2582 | }, 2583 | "funding": [ 2584 | { 2585 | "url": "https://github.com/theseer", 2586 | "type": "github" 2587 | } 2588 | ], 2589 | "time": "2024-03-03T12:36:25+00:00" 2590 | } 2591 | ], 2592 | "aliases": [], 2593 | "minimum-stability": "stable", 2594 | "stability-flags": [], 2595 | "prefer-stable": false, 2596 | "prefer-lowest": false, 2597 | "platform": { 2598 | "ext-json": "*", 2599 | "php": ">=7.4" 2600 | }, 2601 | "platform-dev": [], 2602 | "plugin-api-version": "2.6.0" 2603 | } 2604 | --------------------------------------------------------------------------------