-
Notifications
You must be signed in to change notification settings - Fork 2
fix: preview workspace drafts in TYPO3 v13 #112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
pipaltree
wants to merge
5
commits into
master
Choose a base branch
from
fix/workspace-draft-preview
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
e7e32bd
fix: preview workspace drafts in TYPO3 v13
pipaltree 2ab5490
fix: preview workspace drafts from the record editing form
pipaltree b9add46
fix: build a preview Context per record
maikschneider 6e7cb19
fix: load the sys_workspace record when switching workspace
maikschneider dc96ea5
test: assert the rendered preview shows the draft
maikschneider File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Xima\XimaTypo3Recordlist\Context; | ||
|
|
||
| use TYPO3\CMS\Core\SingletonInterface; | ||
|
|
||
| /** | ||
| * Marks the current request as a record list managed workspace preview. | ||
| * | ||
| * Backend modules of this extension handle the publishing workflow themselves and deliberately bypass the native | ||
| * workspace GUI, so preview URIs have to point to the frontend directly instead of the workspace split preview | ||
| * module. Since TYPO3 core builds preview URIs in several places, the rewriting happens in an event listener, which | ||
| * uses this state to tell "our" preview requests apart from regular workspace usage of the same installation. | ||
| * | ||
| * @see \Xima\XimaTypo3Recordlist\EventListener\WorkspacePreviewUriRewriter | ||
| */ | ||
| class WorkspacePreviewState implements SingletonInterface | ||
| { | ||
| private bool $active = false; | ||
|
|
||
| public function isActive(): bool | ||
| { | ||
| return $this->active; | ||
| } | ||
|
|
||
| public function setActive(bool $active): void | ||
| { | ||
| $this->active = $active; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Xima\XimaTypo3Recordlist\EventListener; | ||
|
|
||
| use TYPO3\CMS\Backend\Routing\Event\BeforePagePreviewUriGeneratedEvent; | ||
| use TYPO3\CMS\Core\Attribute\AsEventListener; | ||
| use TYPO3\CMS\Core\Context\WorkspaceAspect; | ||
| use Xima\XimaTypo3Recordlist\Context\WorkspacePreviewState; | ||
|
|
||
| /** | ||
| * Rewrites workspace preview URIs to direct frontend URIs. | ||
| * | ||
| * As soon as the workspace aspect of the Context is set, EXT:workspaces rewrites every preview URI to the workspace | ||
| * split preview module (Workspaces\Hook\BackendUtilityHook::createPageUriForWorkspaceVersion). That module is the | ||
| * native workspace GUI which the backend modules of this extension replace, and it expects the backend user to have | ||
| * the workspace actively selected. Reset the workspace aspect for the URI generation instead, so that TYPO3 builds a | ||
| * regular frontend URI, and let the CurrentFrontendWorkspaceManipulation middleware apply the workspace in the | ||
| * frontend. PreviewUriBuilder passes a Context given to buildUri() into the event unchanged, so callers have to hand | ||
| * over a Context they can discard afterwards. | ||
| * | ||
| * This affects the view button of the record list as well as every preview URI TYPO3 core builds for the manipulated | ||
| * workspace, most notably the view button of the record editing form (route "record_edit"). | ||
| */ | ||
| final class WorkspacePreviewUriRewriter | ||
| { | ||
| public function __construct( | ||
| private readonly WorkspacePreviewState $workspacePreviewState, | ||
| ) { | ||
| } | ||
|
|
||
| #[AsEventListener( | ||
| identifier: 'xima-typo3-recordlist/workspace-preview-uri', | ||
| before: 'typo3-workspaces/link-modifier' | ||
| )] | ||
| public function rewritePreviewUri(BeforePagePreviewUriGeneratedEvent $event): void | ||
| { | ||
| if (!$this->workspacePreviewState->isActive()) { | ||
| return; | ||
| } | ||
|
|
||
| $workspaceId = (int)$event->getContext()->getPropertyFromAspect('workspace', 'id', 0); | ||
| if ($workspaceId === 0) { | ||
| return; | ||
| } | ||
|
|
||
| $event->getContext()->setAspect('workspace', new WorkspaceAspect(0)); | ||
| // "IGNORE" keeps the regular backend user session instead of initializing a preview user, the workspace | ||
| // itself is applied by CurrentFrontendWorkspaceManipulation | ||
| $event->setAdditionalQueryParameters(array_replace( | ||
| $event->getAdditionalQueryParameters(), | ||
| [ | ||
| 'ADMCMD_prev' => 'IGNORE', | ||
| 'workspaceId' => $workspaceId, | ||
| ] | ||
| )); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { test, expect, FrameLocator } from '@playwright/test'; | ||
| import { loginAsAdmin, openModule } from '../helpers/typo3-backend'; | ||
| import { resetDatabase, resetUserPreferences } from '../helpers/db-reset'; | ||
| import { trackConsoleErrors, ConsoleErrorTracker } from '../helpers/console-errors'; | ||
|
|
||
| // Live uids the fixtures ship a workspace 1 draft version for, in the order the list renders them | ||
| const DRAFT_ORIGINAL_UIDS = ['59', '58']; | ||
|
|
||
| async function previewUri(contentFrame: FrameLocator, originalUid: string): Promise<string> { | ||
| const row = contentFrame.locator(`tr[data-t3ver_oid="${originalUid}"]`); | ||
| await expect(row).toHaveCount(1); | ||
| return (await row.locator('a[target="_blank"]').first().getAttribute('href')) as string; | ||
| } | ||
|
|
||
| test.describe('News Workspace Preview', () => { | ||
| test.beforeAll(() => { resetDatabase(); resetUserPreferences(); }); | ||
|
|
||
| let consoleErrors: ConsoleErrorTracker; | ||
| test.beforeEach(async ({ page }) => { | ||
| // core's workspace-state.js logs this when its in-flight request is aborted by the test teardown | ||
| consoleErrors = trackConsoleErrors(page, [/Failed to fetch workspace info/]); | ||
| await loginAsAdmin(page); | ||
| }); | ||
| test.afterEach(() => { consoleErrors.assertNoErrors(); }); | ||
|
|
||
| test('every workspace draft is previewed in the frontend', async ({ page }) => { | ||
| const contentFrame = await openModule(page, 'example_news'); | ||
|
|
||
| for (const originalUid of DRAFT_ORIGINAL_UIDS) { | ||
| const uri = await previewUri(contentFrame, originalUid); | ||
|
|
||
| expect(uri, `preview URI of draft for record ${originalUid}`).not.toContain('/typo3/workspace/preview-control'); | ||
| expect(uri, `preview URI of draft for record ${originalUid}`).toContain('ADMCMD_prev=IGNORE'); | ||
| expect(uri, `preview URI of draft for record ${originalUid}`).toContain('workspaceId=1'); | ||
| } | ||
| }); | ||
|
|
||
| test('live records keep a plain frontend preview', async ({ page }) => { | ||
| const contentFrame = await openModule(page, 'example_news'); | ||
| const uri = await previewUri(contentFrame, '60'); | ||
|
|
||
| expect(uri).not.toContain('ADMCMD_prev'); | ||
| expect(uri).not.toContain('workspaceId'); | ||
| }); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| }); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.