TYPO3 v15 dev-main snapshot ()

This commit is contained in:
2026-08-10 22:31:09 +02:00
commit af8cc155b5
6818 changed files with 642608 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException;
/**
* Interface AspectInterface
* Think of an aspect like a property bag
*/
interface AspectInterface
{
/**
* Get a property from an aspect
*
* @return mixed
* @throws AspectPropertyNotFoundException
*/
public function get(string $name);
}
+149
View File
@@ -0,0 +1,149 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException;
use TYPO3\CMS\Core\Domain\DateTimeFactory;
use TYPO3\CMS\Core\SingletonInterface;
/**
* Contains the state of a current page request, to be used when reading
* information of the current request in which configuration/context
* it is used.
*
* Typically, the current main context is initialized very early within each entry-point application,
* and is then modified overridden in e.g. PSR-15 middlewares (e.g. authentication, preview settings etc).
*
* For most use-cases, the current main context is fetched via GeneralUtility::makeInstance(Context::class),
* however, if custom settings for a single use-case is necessary, it is recommended to clone the base context:
*
* ```
* $mainContext = GeneralUtility::makeInstance(Context::class);
* $customContext = clone $mainContext;
* $customContext->setAspect(GeneralUtility::makeInstance(VisibilityAspect::class, true, true, false))
* ```
*
* ... which in turn can be injected in the various places where TYPO3 uses contexts.
*
*
* Classic aspect names to be used are:
* - date (DateTimeAspect)
* - workspace
* - visibility
* - frontend.user
* - backend.user
* - language
* - frontend.preview [if EXT:frontend is loaded]
*/
class Context implements SingletonInterface
{
/**
* @var AspectInterface[]
*/
protected array $aspects = [];
/**
* Checks if an aspect exists in the context
*/
public function hasAspect(string $name): bool
{
return match ($name) {
'date', 'visibility', 'backend.user', 'frontend.user', 'workspace', 'language' => true,
default => isset($this->aspects[$name]),
};
}
/**
* Returns an aspect, if it is set
*
* @throws AspectNotFoundException
* @return ($name is 'date' ? DateTimeAspect
* : ($name is 'visibility' ? VisibilityAspect
* : ($name is 'backend.user' ? UserAspect
* : ($name is 'frontend.user' ? UserAspect
* : ($name is 'workspace' ? WorkspaceAspect
* : ($name is 'language' ? LanguageAspect : AspectInterface))))))
*/
public function getAspect(string $name): AspectInterface
{
if (!isset($this->aspects[$name])) {
// Ensure the default aspects are available, this is mostly necessary for tests to not set up everything
switch ($name) {
case 'date':
$this->setAspect('date', new DateTimeAspect(DateTimeFactory::createFromTimestamp($GLOBALS['EXEC_TIME'])));
break;
case 'visibility':
$this->setAspect('visibility', new VisibilityAspect());
break;
case 'backend.user':
$this->setAspect('backend.user', new UserAspect());
break;
case 'frontend.user':
$this->setAspect('frontend.user', new UserAspect());
break;
case 'workspace':
$this->setAspect('workspace', new WorkspaceAspect());
break;
case 'language':
$this->setAspect('language', new LanguageAspect());
break;
default:
throw new AspectNotFoundException('No aspect named "' . $name . '" found.', 1527777641);
}
}
return $this->aspects[$name];
}
/**
* Returns a property from the aspect, but only if the property is found.
*
* @throws AspectNotFoundException
*/
public function getPropertyFromAspect(string $name, string $property, mixed $default = null): mixed
{
if (!$this->hasAspect($name)) {
throw new AspectNotFoundException('No aspect named "' . $name . '" found.', 1527777868);
}
try {
return $this->getAspect($name)->get($property);
} catch (AspectPropertyNotFoundException) {
return $default;
}
}
/**
* Sets an aspect, or overrides an existing aspect if an aspect is already set
*/
public function setAspect(string $name, AspectInterface $aspect): void
{
$this->aspects[$name] = $aspect;
}
/**
* @internal Using this method is a sign of a technical debt. It is used by RedirectService,
* but may vanish any time when this is fixed, and thus internal.
* In general, Context aspects should never have to be unset.
* When a middleware has to use this method, it is either located
* at the wrong position in the chain, or has some other dependency issue.
*/
public function unsetAspect(string $name): void
{
unset($this->aspects[$name]);
}
}
+70
View File
@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException;
/**
* The Aspect is usually available as "date.*" properties in the Context.
*
* Contains the current time + date + timezone,
* and needs a DateTimeImmutable object
*
* Allowed properties:
* - timestamp - unix timestamp number
* - timezone - America/Los_Angeles
* - iso - datetime as string in ISO 8601 format, e.g. `2004-02-12T15:19:21+00:00`
* - full - the DateTimeImmutable object
* - accessTime - 60 seconds precision timestamp
*/
final readonly class DateTimeAspect implements AspectInterface
{
public function __construct(
private \DateTimeImmutable $dateTimeObject,
) {}
/**
* Fetch a property of the date time object or the object itself ("full").
*
* @throws AspectPropertyNotFoundException
*/
public function get(string $name): \DateTimeImmutable|string|int
{
switch ($name) {
case 'timestamp':
return $this->dateTimeObject->getTimestamp();
case 'iso':
return $this->dateTimeObject->format('c');
case 'timezone':
return $this->dateTimeObject->format('e');
case 'full':
return $this->dateTimeObject;
case 'accessTime':
return $this->dateTimeObject->getTimestamp() - ($this->dateTimeObject->getTimestamp() % 60);
}
throw new AspectPropertyNotFoundException('Property "' . $name . '" not found in Aspect "' . __CLASS__ . '".', 1527778767);
}
/**
* Return the full date time object
*/
public function getDateTime(): \DateTimeImmutable
{
return $this->dateTimeObject;
}
}
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context\Exception;
use TYPO3\CMS\Core\Exception;
/**
* Used when an aspect is requested but not found.
*/
class AspectNotFoundException extends Exception {}
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context\Exception;
use TYPO3\CMS\Core\Exception;
/**
* Used when an aspect property is requested but not found.
*/
class AspectPropertyNotFoundException extends Exception {}
+51
View File
@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException;
/**
* The aspect contains the processed file representation that is requested to process locally.
*
* Allowed properties:
* - deferProcessing
*/
final readonly class FileProcessingAspect implements AspectInterface
{
public function __construct(
private bool $deferProcessing = true,
) {}
/**
* Fetch the values
*
* @throws AspectPropertyNotFoundException
*/
public function get(string $name): bool
{
if ($name === 'deferProcessing') {
return $this->deferProcessing;
}
throw new AspectPropertyNotFoundException('Property "' . $name . '" not found in Aspect "' . __CLASS__ . '".', 1599164743);
}
public function isProcessingDeferred(): bool
{
return $this->deferProcessing;
}
}
+159
View File
@@ -0,0 +1,159 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException;
/**
* The Aspect is usually available as "language" property, and
* can be used to find out the "overlay"/data retrieval strategy.
*
*
* "id" (languageId, int)
* - the requested language of the current page (frontend)
* - used in menus and links to generate "links in language with this ID"
*
* "contentId" (int)
* - the language of records to be fetched
* - if empty, "languageId" is used.
*
* "fallbackChain"
* - when "fallback" go with
* - depends on what "contentId" value should be set
* - defined in config.sys_language_mode (strict/content_fallback:4,5,stop/ignore?)
* - defines "contentId" based on "if the current page is available in this language"
* - "strict"
* - "fallback" if current page is not available, check the "fallbackChain"
* - "fallbackAndIgnore"
*
* "overlayType"
* - defines which way the records should be fetched from
* - usually you fetch language 0 and -1, then take the "contentId" and "overlay" them
* - here you have two choices
* 1. "on" if there is no overlay, do not render the default language records ("hideNonTranslated")
* 2. "mixed" - if there is no overlay, just keep the default language, possibility to have mixed languages - config.sys_language_overlay = 1
* 3. "off" - do not do overlay, only fetch records available in the current "contentId" (see above), and do not care about overlays or fallbacks - fallbacks could be an option here, actually that is placed on top
* 4. "includeFloating" - on + includeRecordsWithoutDefaultTranslation
*/
final readonly class LanguageAspect implements AspectInterface
{
public const string OVERLAYS_OFF = 'off'; // config.sys_language_overlay = 0
public const string OVERLAYS_MIXED = 'mixed'; // config.sys_language_overlay = 1 (keep the ones that are only available in default language)
public const string OVERLAYS_ON = 'on'; // "hideNonTranslated"
public const string OVERLAYS_ON_WITH_FLOATING = 'includeFloating'; // "hideNonTranslated" + records that are only available in polish
/**
* Create the default language
*/
public function __construct(
private int $id = 0,
private ?int $contentId = null,
private string $overlayType = self::OVERLAYS_ON_WITH_FLOATING,
private array $fallbackChain = [],
) {}
/**
* Used language overlay
*/
public function getOverlayType(): string
{
return $this->overlayType;
}
/**
* Returns the language ID the current page was requested,
* this is relevant when building menus or links to other pages.
*/
public function getId(): int
{
return $this->id;
}
/**
* Contains the language UID of the content records that should be overlaid to would be fetched.
* This is especially useful when a page requested with language=4 should fall back to showing
* content of language=2 (see fallbackChain)
*/
public function getContentId(): int
{
return $this->contentId ?? $this->id;
}
public function getFallbackChain(): array
{
return $this->fallbackChain;
}
/**
* Whether overlays should be done
*/
public function doOverlays(): bool
{
return $this->getContentId() > 0 && $this->overlayType !== self::OVERLAYS_OFF;
}
/**
* Here for compatibility reasons
*/
public function getLegacyLanguageMode(): string
{
if ($this->fallbackChain === ['off']) {
return '';
}
if (empty($this->fallbackChain)) {
return 'strict';
}
return 'content_fallback';
}
/**
* Here for compatibility reasons
*/
public function getLegacyOverlayType(): string
{
return match ($this->overlayType) {
self::OVERLAYS_ON_WITH_FLOATING, self::OVERLAYS_ON => 'hideNonTranslated',
self::OVERLAYS_MIXED => '1',
default => '0',
};
}
/**
* Fetch a property.
*
* @throws AspectPropertyNotFoundException
*/
public function get(string $name): int|string|array
{
switch ($name) {
case 'id':
return $this->id;
case 'contentId':
return $this->getContentId();
case 'fallbackChain':
return $this->fallbackChain;
case 'overlayType':
return $this->overlayType;
case 'legacyLanguageMode':
return $this->getLegacyLanguageMode();
case 'legacyOverlayType':
return $this->getLegacyOverlayType();
}
throw new AspectPropertyNotFoundException('Property "' . $name . '" not found in Aspect "' . __CLASS__ . '".', 1530448504);
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
/**
* A simple factory to create a language aspect.
*/
final readonly class LanguageAspectFactory
{
/**
* Site Languages always run with overlays + floating records.
*/
public static function createFromSiteLanguage(SiteLanguage $language): LanguageAspect
{
$languageId = $language->getLanguageId();
$fallbackType = $language->getFallbackType();
$fallbackOrder = $language->getFallbackLanguageIds();
$fallbackOrder[] = 'pageNotFound';
switch ($fallbackType) {
// Fall back to other language, if the page does not exist in the requested language
// But always fetch only records of this specific (available) language
case 'free':
$overlayType = LanguageAspect::OVERLAYS_OFF;
break;
// Fall back to other language, if the page does not exist in the requested language
// Do overlays, and keep the ones that are not translated
case 'fallback':
$overlayType = LanguageAspect::OVERLAYS_MIXED;
break;
// Same as "fallback" but remove the records that are not translated
case 'strict':
$overlayType = LanguageAspect::OVERLAYS_ON_WITH_FLOATING;
break;
// Ignore, fallback to default language
default:
$fallbackOrder = [0];
$overlayType = LanguageAspect::OVERLAYS_OFF;
}
return new LanguageAspect($languageId, $languageId, $overlayType, $fallbackOrder);
}
}
+107
View File
@@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Security\Nonce;
use TYPO3\CMS\Core\Security\NoncePool;
use TYPO3\CMS\Core\Security\RequestToken;
use TYPO3\CMS\Core\Security\SigningSecretResolver;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* @internal
*/
class SecurityAspect implements AspectInterface
{
/**
* `null` in case no request token was received
* `false` in case a request token was received, which was invalid
*/
protected RequestToken|false|null $receivedRequestToken = null;
protected SigningSecretResolver $signingSecretResolver;
protected NoncePool $noncePool;
public static function provideIn(Context $context): self
{
if ($context->hasAspect('security')) {
$securityAspect = $context->getAspect('security');
}
if (!isset($securityAspect) || !$securityAspect instanceof SecurityAspect) {
$securityAspect = GeneralUtility::makeInstance(SecurityAspect::class);
$context->setAspect('security', $securityAspect);
}
return $securityAspect;
}
public function __construct()
{
$this->noncePool = GeneralUtility::makeInstance(NoncePool::class);
$this->signingSecretResolver = GeneralUtility::makeInstance(
SigningSecretResolver::class,
[
'nonce' => $this->noncePool,
// @todo enrich in separate step with `*FormProtection`
]
);
}
public function get(string $name): bool|Nonce|RequestToken|null
{
return match ($name) {
'receivedRequestToken' => $this->receivedRequestToken,
'signingSecretResolver' => $this->signingSecretResolver,
'noncePool' => $this->noncePool,
default => null,
};
}
public function getReceivedRequestToken(): RequestToken|false|null
{
return $this->receivedRequestToken;
}
public function setReceivedRequestToken(RequestToken|false|null $receivedRequestToken): void
{
$this->receivedRequestToken = $receivedRequestToken;
}
/**
* Resolves corresponding signing secret providers (such as `NoncePool`).
* Example: `...->getSigningSecretResolver->findByType('nonce')` resolves `NoncePool`
*/
public function getSigningSecretResolver(): SigningSecretResolver
{
return $this->signingSecretResolver;
}
public function getNoncePool(): NoncePool
{
return $this->noncePool;
}
/**
* Shortcut function to `NoncePool`, providing a `SigningSecret`
* @todo this is a "comfort function", might be dropped
*/
public function provideNonce(): Nonce
{
return $this->noncePool->provideSigningSecret();
}
}
+154
View File
@@ -0,0 +1,154 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Authentication\AbstractUserAuthentication;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException;
use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
/**
* The aspect contains information about a user.
* Can be used for frontend and backend users.
*
* Allowed properties:
* - id
* - username
* - isLoggedIn
* - isAdmin
* - groupIds (Array of Ids)
* - groupNames
*/
final readonly class UserAspect implements AspectInterface
{
/**
* @param AbstractUserAuthentication|null $user
* @param array|null $alternativeGroups Alternative list of groups, usually useful for frontend logins with "magic" groups like "-1" and "-2"
*/
public function __construct(
private ?AbstractUserAuthentication $user = null,
private ?array $alternativeGroups = null
) {}
/**
* Fetch common information about the user
*
* @throws AspectPropertyNotFoundException
*/
public function get(string $name): int|bool|string|array
{
switch ($name) {
case 'id':
return (int)($this->user?->user[$this->user->userid_column] ?? 0);
case 'username':
return (string)($this->user?->user[$this->user->username_column] ?? '');
case 'isLoggedIn':
return $this->isLoggedIn();
case 'isAdmin':
return $this->isAdmin();
case 'groupIds':
return $this->getGroupIds();
case 'groupNames':
return $this->getGroupNames();
}
throw new AspectPropertyNotFoundException('Property "' . $name . '" not found in Aspect "' . __CLASS__ . '".', 1529996567);
}
/**
* A user is logged in if the user has a UID, but does not care about groups.
*
* For frontend purposes, it is possible to e.g. simulate groups, but this would still be defined as "not logged in".
*
* For backend, only the check on the user ID is used.
*/
public function isLoggedIn(): bool
{
return ($this->user?->user[$this->user->userid_column] ?? 0) > 0;
}
/**
* Check if admin is set
*/
public function isAdmin(): bool
{
if ($this->user instanceof BackendUserAuthentication) {
// Only backend users have the admin flag at all.
return $this->user->isAdmin();
}
return false;
}
/**
* Return the groups the user is a member of
*
* For Frontend Users there are two special groups:
* "-1" = hide at login
* "-2" = show at any login
*/
public function getGroupIds(): array
{
// Alternative groups are set
if (is_array($this->alternativeGroups)) {
return $this->alternativeGroups;
}
if ($this->user instanceof BackendUserAuthentication) {
return $this->user->userGroupsUID;
}
$groups = [];
if ($this->user instanceof FrontendUserAuthentication) {
if ($this->isLoggedIn()) {
// If a user is logged in, always add "-2"
$groups = [0, -2];
if (!empty($this->user->userGroups)) {
$groups = array_merge($groups, array_keys($this->user->userGroups));
}
} else {
$groups = [0, -1];
}
}
return $groups;
}
/**
* Get the name of all groups, used in Fluid's IfHasRole ViewHelper
*/
public function getGroupNames(): array
{
$groupNames = [];
if ($this->user instanceof AbstractUserAuthentication) {
foreach ($this->user->userGroups as $userGroup) {
$groupNames[] = $userGroup['title'];
}
}
return $groupNames;
}
/**
* Checking if a user is logged in or a group constellation different from "0,-1"
*
* @return bool TRUE if either a login user is found OR if the group list is set to something else than '0,-1' (could be done even without a user being logged in!)
*/
public function isUserOrGroupSet(): bool
{
if ($this->user instanceof FrontendUserAuthentication) {
$groups = $this->getGroupIds();
return $this->isLoggedIn() || implode(',', $groups) !== '0,-1';
}
return $this->isLoggedIn();
}
}
+90
View File
@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException;
/**
* The aspect contains whether to show hidden pages, records (content) or even deleted records.
*
* Allowed properties:
* - includeHiddenPages
* - includeHiddenContent
* - includeDeletedRecords
* - includeScheduledRecords
*/
final readonly class VisibilityAspect implements AspectInterface
{
/**
* @param bool $includeHiddenPages whether to include hidden=1 in pages tables
* @param bool $includeHiddenContent whether to include hidden=1 in tables except for pages
* @param bool $includeScheduledRecords whether to ignore access time in tables
* @param bool $includeDeletedRecords whether to include deleted=1 records (only for use in recycler)
*/
public function __construct(
private bool $includeHiddenPages = false,
private bool $includeHiddenContent = false,
private bool $includeDeletedRecords = false,
private bool $includeScheduledRecords = false,
) {}
/**
* Fetch the values
*
* @throws AspectPropertyNotFoundException
*/
public function get(string $name): bool
{
switch ($name) {
case 'includeHiddenPages':
return $this->includeHiddenPages;
case 'includeHiddenContent':
return $this->includeHiddenContent;
case 'includeDeletedRecords':
return $this->includeDeletedRecords;
case 'includeScheduledRecords':
return $this->includeScheduledRecords;
}
throw new AspectPropertyNotFoundException('Property "' . $name . '" not found in Aspect "' . __CLASS__ . '".', 1527780439);
}
public function includeHidden(): bool
{
return $this->includeHiddenContent || $this->includeHiddenPages;
}
public function includeHiddenPages(): bool
{
return $this->includeHiddenPages;
}
public function includeHiddenContent(): bool
{
return $this->includeHiddenContent;
}
public function includeScheduledRecords(): bool
{
return $this->includeScheduledRecords;
}
public function includeDeletedRecords(): bool
{
return $this->includeDeletedRecords;
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Context;
use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException;
/**
* The aspect contains information about the currently accessed workspace.
*
* Allowed properties:
* - id
* - isLive
* - isOffline
*/
final readonly class WorkspaceAspect implements AspectInterface
{
public function __construct(
private int $workspaceId = 0,
) {}
/**
* Fetch the workspace ID, or evaluated the state if it's 'online' or 'offline'
*
* @throws AspectPropertyNotFoundException
*/
public function get(string $name): int|bool
{
switch ($name) {
case 'id':
return $this->workspaceId;
case 'isLive':
return $this->isLive();
case 'isOffline':
return !$this->isLive();
}
throw new AspectPropertyNotFoundException('Property "' . $name . '" not found in Aspect "' . __CLASS__ . '".', 1527779447);
}
/**
* Return the workspace ID
*/
public function getId(): int
{
return $this->workspaceId;
}
/**
* Return whether this is live workspace or in a custom offline workspace
*/
public function isLive(): bool
{
return $this->workspaceId === 0;
}
}