Content and scope handed to the saver. */ private array $saved = []; private int $backups = 0; /** Change log of the writer; null = DiviWriterFixture::log() (records only). */ private ?FakeChangeLog $log = null; /** Thrown by the saver instead of saving, if set. */ private ?\Throwable $failure = null; /** @var list Live (published, private, scheduled) posts that show the global entry (ruling P8a). */ private array $live = [1053]; private bool $trash = true; protected function setUp(): void { parent::setUp(); Functions\when('wp_revisions_enabled')->justReturn(true); Functions\when('_prime_post_caches')->justReturn(null); } /** @var list Normal (non-global) entries that pages nevertheless show (audit L2). */ private array $referenced = []; /** * For the global entries and $this->referenced: the live posts ($this->live; 1053 published, the * others private) and draft 1070. Other entries are shown nowhere. */ private function usages(): GlobalUsages { return LibraryFixtures::usages(fn (int $id): array => ! LibraryFixtures::ITEMS[$id][2] && ! in_array($id, $this->referenced, true) ? [] : array_merge( array_map( static fn (int $id): array => ['id' => $id, 'status' => $id === 1053 ? 'publish' : 'private', 'type' => 'page'], $this->live ), [['id' => 1070, 'status' => 'draft', 'type' => 'page']] )); } /** @param list $deniedRoles */ private function writer(bool $writable = true, array $deniedRoles = []): DiviWriter { $saver = Mockery::mock(DiviSaver::class); $saver->allows('save')->andReturnUsing(function (WP_Post $post, string $content, SaveScope $scope): array { if ($this->failure !== null) { throw $this->failure; } $this->saved[] = [$content, $scope]; $post->post_content = $content; return ['revision_id' => 811, 'warnings' => []]; }); $access = LibraryFixtures::access($deniedRoles, $writable); $design = DiviWriterFixture::designReader(); $globals = new GlobalEdits( $access, $this->usages(), function (WP_Post $item): int { ++$this->backups; return 1071; }, trashEnabled: fn (): bool => $this->trash ); return new DiviWriter( LibraryFixtures::loader($access), $saver, $this->log ?? DiviWriterFixture::log(), $design, DiviWriterFixture::composition($design), $globals ); } private static function rev(int $id): string { return Rev::of((string) LibraryFixtures::item($id)->post_content); } /** @return array */ private static function relabel(int $id, bool $confirm = false): array { return array_merge( ['post_id' => $id, 'tree_rev' => self::rev($id), 'changes' => [['id' => 'm0', 'label' => 'Neu']]], $confirm ? ['confirm' => true] : [] ); } /** A user with every capability but $cap on the posts $ids. */ private static function denyOn(string $cap, array $ids): void { Functions\when('current_user_can')->alias( static fn (string $asked, mixed ...$args): bool => ! ($asked === $cap && ($ids === [] || in_array((int) ($args[0] ?? 0), $ids, true))) ); } public function testPlainLibraryItemIsSavedWithoutConfirmAndWithoutPageFlags(): void { LibraryFixtures::given([LibraryFixtures::item(1057)]); $result = (new DiviUpdateAbility($this->writer()))->execute(self::relabel(1057)); self::assertTrue($result['ok']); self::assertSame(SaveScope::LibraryItem, $this->saved[0][1]); self::assertStringStartsWith('