Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.5.1

- Corrected the write-permission wording on `TaskClient::publish()`/`unpublish()`: the OpenAPI spec
states that both `isPublic` and `publicConfig` require write permission to the task's Actor, not
(as `unpublish()`'s docblock previously claimed) permission to the task alone. `publish()`'s
docblock now also states the Actor's fewer-than-50-published-tasks limit.
- `docs/tasks.md` updated to match.

## 0.5.0

Breaking: `RequestQueueClient` methods that previously returned a raw `array<string,mixed>` (or, for
Expand Down
5 changes: 3 additions & 2 deletions docs/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ foreach ($client->tasks()->iterate(new ListOptions(), 50) as $t) {

- `get(): ?Task`, `update(mixed $newFields): Task`, `delete(): void`
- `publish(): Task`, `unpublish(): Task` — publish/unpublish the task's public landing page, by
setting `isPublic` through `update()`. Publishing requires the task's Actor to be public and the
task to already have its `publicConfig` set up.
setting `isPublic` through `update()`. Both require write permission to the task's Actor;
publishing additionally requires the Actor to be public, to have fewer than 50 already-published
tasks, and the task's `publicConfig.inputSchemaFields`/`publicConfig.datasetView` to be set.
- `start(mixed $input = null, ?TaskStartOptions $options = null): ActorRun`
- `call(mixed $input = null, ?TaskStartOptions $options = null, ?int $waitSecs = null): ActorRun`
- `getInput(): mixed`, `updateInput(mixed $input): mixed`
Expand Down
17 changes: 9 additions & 8 deletions src/Resource/TaskClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ public function delete(): void

/**
* Publishes the task on its public landing page, by setting {@code isPublic} through
* {@see update()}.
* {@see update()}. Requires write permission to the task's Actor.
*
* The task's Actor must be public and the task must have its public display configuration
* ({@code publicConfig}) set up first. Requires write permission to both the task and its
* Actor. Publishing an already published task does nothing.
* To publish, the task's Actor must be public, its {@code publicConfig.inputSchemaFields} and
* {@code publicConfig.datasetView} must be set, and the Actor must have fewer than 50
* published tasks; if any of these are not met, the request fails and nothing is changed.
* Publishing an already published task does nothing.
*/
public function publish(): Task
{
Expand All @@ -72,12 +73,12 @@ public function publish(): Task

/**
* Unpublishes the task from its public landing page, by setting {@code isPublic} through
* {@see update()}.
* {@see update()}. Like {@see publish()}, this requires write permission to the task's Actor:
* the API requires Actor write permission for both {@code isPublic} and {@code publicConfig}.
*
* The public display configuration ({@code publicConfig}) is preserved, so the task can be
* published again without re-entering it. Unlike {@see publish()}, this only requires write
* permission to the task itself (not its Actor), since it does not need to validate the
* Actor's public/display eligibility. Unpublishing a task that is not published does nothing.
* published again without re-entering it. Unpublishing a task that is not published does
* nothing.
*/
public function unpublish(): Task
{
Expand Down
2 changes: 1 addition & 1 deletion src/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class Version
* The semantic version of this client library (see https://semver.org/).
* Changes to the public interface other than additive ones are considered breaking changes.
*/
public const CLIENT_VERSION = '0.5.0';
public const CLIENT_VERSION = '0.5.1';

/**
* The version of the Apify OpenAPI specification this client was generated and verified
Expand Down
56 changes: 56 additions & 0 deletions tests/Unit/TaskPublishUnpublishTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Apify\Client\Tests\Unit;

use Apify\Client\ApifyClient;
use Apify\Client\Internal\Json;
use PHPUnit\Framework\TestCase;

/**
* Offline behavioral tests for {@see \Apify\Client\Resource\TaskClient::publish()} and
* {@see \Apify\Client\Resource\TaskClient::unpublish()}: both are thin wrappers around
* {@see \Apify\Client\Resource\TaskClient::update()}, so what needs covering offline is the exact
* request they send (method, path, body), independent of the live-API-dependent behavior already
* exercised by {@see \Apify\Client\Tests\Integration\TaskIntegrationTest::testPublishUnpublish()}.
*/
final class TaskPublishUnpublishTest extends TestCase
{
private function client(MockTransport $transport): ApifyClient
{
return new ApifyClient(token: 't', httpClient: $transport);
}

public function testPublishSendsIsPublicTrue(): void
{
$transport = (new MockTransport())->queueResponse(200, Json::encode(['data' => [
'id' => 'task1',
'isPublic' => true,
]]));

$task = $this->client($transport)->task('task1')->publish();

self::assertTrue($task->isPublic());
$request = $transport->lastRequest();
self::assertSame('PUT', $request->getMethod());
self::assertStringContainsString('/actor-tasks/task1', (string) $request->getUri());
self::assertSame(['isPublic' => true], Json::decode(MockTransport::readBody($request)));
}

public function testUnpublishSendsIsPublicFalse(): void
{
$transport = (new MockTransport())->queueResponse(200, Json::encode(['data' => [
'id' => 'task1',
'isPublic' => false,
]]));

$task = $this->client($transport)->task('task1')->unpublish();

self::assertNotTrue($task->isPublic());
$request = $transport->lastRequest();
self::assertSame('PUT', $request->getMethod());
self::assertStringContainsString('/actor-tasks/task1', (string) $request->getUri());
self::assertSame(['isPublic' => false], Json::decode(MockTransport::readBody($request)));
}
}
Loading