first commit

This commit is contained in:
salam committed 2026-10-19 08:18:39 +02:00
commit 1218dd1517
12716 files changed
+989233

No files matched your search

@@ -0,0 +1,128 @@
<?php
namespace TYPO3\CMS\Extensionmanager\Domain\Model;
/*
* 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!
*/
/**
* Main extension model
* @internal This class is a specific domain model implementation and is not part of the Public TYPO3 API.
*/
class Dependency extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* @var string
*/
protected $identifier = '';
/**
* @var string
*/
protected $lowestVersion = '';
/**
* @var string
*/
protected $highestVersion = '';
/**
* @var string
*/
protected $type = '';
/**
* @var array
*/
protected static $dependencyTypes = [
'depends',
'conflicts',
'suggests'
];
/**
* @var array
*/
public static $specialDependencies = [
'typo3',
'php'
];
/**
* @param string $highestVersion
*/
public function setHighestVersion($highestVersion)
{
$this->highestVersion = $highestVersion;
}
/**
* @return string
*/
public function getHighestVersion()
{
return $this->highestVersion;
}
/**
* @param string $identifier
*/
public function setIdentifier($identifier)
{
$this->identifier = $identifier;
}
/**
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* @param string $lowestVersion
*/
public function setLowestVersion($lowestVersion)
{
$this->lowestVersion = $lowestVersion;
}
/**
* @return string
*/
public function getLowestVersion()
{
return $this->lowestVersion;
}
/**
* @param string $type
* @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException if no valid dependency type was given
*/
public function setType($type)
{
if (in_array($type, self::$dependencyTypes)) {
$this->type = $type;
} else {
throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException($type . ' was not a valid dependency type.', 1476122402);
}
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
}
@@ -0,0 +1,254 @@
<?php
namespace TYPO3\CMS\Extensionmanager\Domain\Model;
/*
* 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!
*/
use TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException;
/**
* Download Queue - storage for extensions to be downloaded
* @internal This class is a specific domain model implementation and is not part of the Public TYPO3 API.
*/
class DownloadQueue implements \TYPO3\CMS\Core\SingletonInterface
{
/**
* Storage for extensions to be downloaded
*
* @var Extension[string][string]
*/
protected $extensionStorage = [];
/**
* Storage for extensions to be installed
*
* @var array
*/
protected $extensionInstallStorage = [];
/**
* Storage for extensions to be copied
*
* @var array
*/
protected $extensionCopyStorage = [];
/**
* @var \TYPO3\CMS\Extensionmanager\Utility\ListUtility
*/
protected $listUtility;
/**
* @param \TYPO3\CMS\Extensionmanager\Utility\ListUtility $listUtility
*/
public function injectListUtility(\TYPO3\CMS\Extensionmanager\Utility\ListUtility $listUtility)
{
$this->listUtility = $listUtility;
}
/**
* Adds an extension to the download queue.
* If the extension was already requested in a different version
* an exception is thrown.
*
* @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
* @param string $stack
* @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
*/
public function addExtensionToQueue(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension, $stack = 'download')
{
if (!is_string($stack) || !in_array($stack, ['download', 'update'])) {
throw new ExtensionManagerException('Stack has to be either "download" or "update"', 1342432103);
}
if (!isset($this->extensionStorage[$stack])) {
$this->extensionStorage[$stack] = [];
}
if (array_key_exists($extension->getExtensionKey(), $this->extensionStorage[$stack])) {
if ($this->extensionStorage[$stack][$extension->getExtensionKey()] !== $extension) {
throw new ExtensionManagerException(
$extension->getExtensionKey() . ' was requested to be downloaded in different versions (' . $extension->getVersion()
. ' and ' . $this->extensionStorage[$stack][$extension->getExtensionKey()]->getVersion() . ').',
1342432101
);
}
}
$this->extensionStorage[$stack][$extension->getExtensionKey()] = $extension;
}
/**
* @return array
*/
public function getExtensionQueue()
{
return $this->extensionStorage;
}
/**
* Remove an extension from download queue
*
* @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
* @param string $stack Stack to remove extension from (download, update or install)
* @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
*/
public function removeExtensionFromQueue(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension, $stack = 'download')
{
if (!is_string($stack) || !in_array($stack, ['download', 'update'])) {
throw new ExtensionManagerException('Stack has to be either "download" or "update"', 1342432104);
}
if (array_key_exists($stack, $this->extensionStorage) && is_array($this->extensionStorage[$stack])) {
if (array_key_exists($extension->getExtensionKey(), $this->extensionStorage[$stack])) {
unset($this->extensionStorage[$stack][$extension->getExtensionKey()]);
}
}
}
/**
* Adds an extension to the install queue for later installation
*
* @param Extension $extension
*/
public function addExtensionToInstallQueue($extension)
{
$this->extensionInstallStorage[$extension->getExtensionKey()] = $extension;
}
/**
* Removes an extension from the install queue
*
* @param string $extensionKey
*/
public function removeExtensionFromInstallQueue($extensionKey)
{
if (array_key_exists($extensionKey, $this->extensionInstallStorage)) {
unset($this->extensionInstallStorage[$extensionKey]);
}
}
/**
* Adds an extension to the copy queue for later copying
*
* @param string $extensionKey
* @param string $sourceFolder
*/
public function addExtensionToCopyQueue($extensionKey, $sourceFolder)
{
$this->extensionCopyStorage[$extensionKey] = $sourceFolder;
}
/**
* Remove an extension from extension copy storage
*
* @param $extensionKey
*/
public function removeExtensionFromCopyQueue($extensionKey)
{
if (array_key_exists($extensionKey, $this->extensionCopyStorage)) {
unset($this->extensionCopyStorage[$extensionKey]);
}
}
/**
* Gets the extension installation queue
*
* @return array
*/
public function getExtensionInstallStorage()
{
return $this->extensionInstallStorage;
}
/**
* Gets the extension copy queue
*
* @return array
*/
public function getExtensionCopyStorage()
{
return $this->extensionCopyStorage;
}
/**
* Return whether the queue contains extensions or not
*
* @param string $stack
* @return bool
*/
public function isQueueEmpty($stack = 'download')
{
return empty($this->extensionStorage[$stack]);
}
/**
* Return whether the copy queue contains extensions or not
*
* @return bool
*/
public function isCopyQueueEmpty()
{
return empty($this->extensionCopyStorage);
}
/**
* Return whether the install queue contains extensions or not
*
* @return bool
*/
public function isInstallQueueEmpty()
{
return empty($this->extensionInstallStorage);
}
/**
* Resets the extension queue and returns old extensions
*
* @param string|null $stack if null, all stacks are reset
* @return array
*/
public function resetExtensionQueue($stack = null)
{
$storage = [];
if ($stack === null) {
$storage = $this->extensionStorage;
$this->extensionStorage = [];
} elseif (isset($this->extensionStorage[$stack])) {
$storage = $this->extensionStorage[$stack];
$this->extensionStorage[$stack] = [];
}
return $storage;
}
/**
* Resets the copy queue and returns the old extensions
* @return array
*/
public function resetExtensionCopyStorage()
{
$storage = $this->extensionCopyStorage;
$this->extensionCopyStorage = [];
return $storage;
}
/**
* Resets the install queue and returns the old extensions
* @return array
*/
public function resetExtensionInstallStorage()
{
$storage = $this->extensionInstallStorage;
$this->extensionInstallStorage = [];
return $storage;
}
}
@@ -0,0 +1,602 @@
<?php
namespace TYPO3\CMS\Extensionmanager\Domain\Model;
/*
* 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!
*/
use TYPO3\CMS\Core\Core\Environment;
/**
* Main extension model
* @internal This class is a specific domain model implementation and is not part of the Public TYPO3 API.
*/
class Extension extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* Category index for distributions
*/
const DISTRIBUTION_CATEGORY = 10;
/**
* Contains default categories.
*
* @var array
*/
protected static $defaultCategories = [
0 => 'be',
1 => 'module',
2 => 'fe',
3 => 'plugin',
4 => 'misc',
5 => 'services',
6 => 'templates',
8 => 'doc',
9 => 'example',
self::DISTRIBUTION_CATEGORY => 'distribution'
];
/**
* Contains default states.
*
* @var array
*/
protected static $defaultStates = [
0 => 'alpha',
1 => 'beta',
2 => 'stable',
3 => 'experimental',
4 => 'test',
5 => 'obsolete',
6 => 'excludeFromUpdates',
7 => 'deprecated',
999 => 'n/a'
];
/**
* @var \TYPO3\CMS\Extbase\Object\ObjectManager
*/
protected $objectManager;
/**
* @var string
*/
protected $extensionKey = '';
/**
* @var string
*/
protected $version = '';
/**
* @var int
*/
protected $integerVersion = 0;
/**
* @var string
*/
protected $title = '';
/**
* @var string
*/
protected $description = '';
/**
* @var int
*/
protected $state = 0;
/**
* @var int
*/
protected $category = 0;
/**
* @var \DateTime
*/
protected $lastUpdated;
/**
* @var string
*/
protected $updateComment = '';
/**
* @var string
*/
protected $authorName = '';
/**
* @var string
*/
protected $authorEmail = '';
/**
* @var bool
*/
protected $currentVersion = false;
/**
* @var string
*/
protected $md5hash = '';
/**
* @var int
*/
protected $reviewState;
/**
* @var int
*/
protected $alldownloadcounter;
/**
* @var string
*/
protected $serializedDependencies = '';
/**
* @var \SplObjectStorage<\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency>
*/
protected $dependencies;
/**
* @internal
* @var int
*/
protected $position = 0;
/**
* @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
*/
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
/**
* @param string $authorEmail
*/
public function setAuthorEmail($authorEmail)
{
$this->authorEmail = $authorEmail;
}
/**
* @return string
*/
public function getAuthorEmail()
{
return $this->authorEmail;
}
/**
* @param string $authorName
*/
public function setAuthorName($authorName)
{
$this->authorName = $authorName;
}
/**
* @return string
*/
public function getAuthorName()
{
return $this->authorName;
}
/**
* @param int $category
*/
public function setCategory($category)
{
$this->category = $category;
}
/**
* @return int
*/
public function getCategory()
{
return $this->category;
}
/**
* Get Category String
*
* @return string
*/
public function getCategoryString()
{
$categoryString = '';
if (isset(self::$defaultCategories[$this->getCategory()])) {
$categoryString = self::$defaultCategories[$this->getCategory()];
}
return $categoryString;
}
/**
* Returns category index from a given string or an integer.
* Fallback to 4 - 'misc' in case string is not found or integer ist out of range.
*
* @param string|int $category Category string or integer
* @return int Valid category index
*/
public function getCategoryIndexFromStringOrNumber($category)
{
$categoryIndex = 4;
if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($category)) {
$categoryIndex = (int)$category;
if ($categoryIndex < 0 || $categoryIndex > 10) {
$categoryIndex = 4;
}
} elseif (is_string($category)) {
$categoryIndex = array_search($category, self::$defaultCategories);
if ($categoryIndex === false) {
$categoryIndex = 4;
}
}
return $categoryIndex;
}
/**
* @param string $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* @param string $extensionKey
*/
public function setExtensionKey($extensionKey)
{
$this->extensionKey = $extensionKey;
}
/**
* @return string
*/
public function getExtensionKey()
{
return $this->extensionKey;
}
/**
* @param \DateTime $lastUpdated
*/
public function setLastUpdated(\DateTime $lastUpdated)
{
$this->lastUpdated = $lastUpdated;
}
/**
* @return \DateTime
*/
public function getLastUpdated()
{
return $this->lastUpdated;
}
/**
* @param int $state
*/
public function setState($state)
{
$this->state = $state;
}
/**
* @return int
*/
public function getState()
{
return $this->state;
}
/**
* Get State string
*
* @return string
*/
public function getStateString()
{
$stateString = '';
if (isset(self::$defaultStates[$this->getState()])) {
$stateString = self::$defaultStates[$this->getState()];
}
return $stateString;
}
/**
* Returns either array with all default states or index/title
* of a state entry.
*
* @param mixed $state state title or state index
* @return mixed
*/
public function getDefaultState($state = null)
{
$defaultState = '';
if ($state === null) {
$defaultState = self::$defaultStates;
} else {
if (is_string($state)) {
$stateIndex = array_search(strtolower($state), self::$defaultStates);
if ($stateIndex === false) {
// default state
$stateIndex = 999;
}
$defaultState = $stateIndex;
} else {
if (is_int($state) && $state >= 0) {
if (array_key_exists($state, self::$defaultStates)) {
$stateTitle = self::$defaultStates[$state];
} else {
// default state
$stateTitle = 'n/a';
}
$defaultState = $stateTitle;
}
}
}
return $defaultState;
}
/**
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $updateComment
*/
public function setUpdateComment($updateComment)
{
$this->updateComment = $updateComment;
}
/**
* @return string
*/
public function getUpdateComment()
{
return $this->updateComment;
}
/**
* @param string $version
*/
public function setVersion($version)
{
$this->version = $version;
}
/**
* @return string
*/
public function getVersion()
{
return $this->version;
}
/**
* @param bool $currentVersion
*/
public function setCurrentVersion($currentVersion)
{
$this->currentVersion = $currentVersion;
}
/**
* @return bool
*/
public function getCurrentVersion()
{
return $this->currentVersion;
}
/**
* @param string $md5hash
*/
public function setMd5hash($md5hash)
{
$this->md5hash = $md5hash;
}
/**
* @return string
*/
public function getMd5hash()
{
return $this->md5hash;
}
/**
* Possible install paths
*
* @static
* @return array
*/
public static function returnInstallPaths()
{
$installPaths = [
'System' => Environment::getFrameworkBasePath() . '/',
'Global' => Environment::getBackendPath() . '/ext/',
'Local' => Environment::getExtensionsPath() . '/'
];
return $installPaths;
}
/**
* Allowed install paths
*
* @static
* @return array
*/
public static function returnAllowedInstallPaths()
{
$installPaths = self::returnInstallPaths();
if (empty($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'])) {
unset($installPaths['Global']);
}
if (empty($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'])) {
unset($installPaths['Local']);
}
return $installPaths;
}
/**
* Allowed install names: System, Global, Local
*
* @static
* @return array
*/
public static function returnAllowedInstallTypes()
{
$installPaths = self::returnAllowedInstallPaths();
return array_keys($installPaths);
}
/**
* @param string $dependencies
*/
public function setSerializedDependencies($dependencies)
{
$this->serializedDependencies = $dependencies;
}
/**
* @return string
*/
public function getSerializedDependencies()
{
return $this->serializedDependencies;
}
/**
* @param \SplObjectStorage $dependencies
*/
public function setDependencies($dependencies)
{
$this->dependencies = $dependencies;
}
/**
* @return \SplObjectStorage
*/
public function getDependencies()
{
if (!is_object($this->dependencies)) {
/** @var \TYPO3\CMS\Extensionmanager\Utility\ExtensionModelUtility $extensionModelUtility */
$extensionModelUtility = $this->objectManager->get(\TYPO3\CMS\Extensionmanager\Utility\ExtensionModelUtility::class);
$this->setDependencies($extensionModelUtility->convertDependenciesToObjects($this->getSerializedDependencies()));
}
return $this->dependencies;
}
/**
* @param \TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependency
*/
public function addDependency(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependency)
{
$this->dependencies->attach($dependency);
}
/**
* @param int $integerVersion
*/
public function setIntegerVersion($integerVersion)
{
$this->integerVersion = $integerVersion;
}
/**
* @return int
*/
public function getIntegerVersion()
{
return $this->integerVersion;
}
/**
* @param int $reviewState
*/
public function setReviewState($reviewState)
{
$this->reviewState = $reviewState;
}
/**
* @return int
*/
public function getReviewState()
{
return $this->reviewState;
}
/**
* @param int $position
*/
public function setPosition($position)
{
$this->position = $position;
}
/**
* @return int
*/
public function getPosition()
{
return $this->position;
}
/**
* @param int $alldownloadcounter
*/
public function setAlldownloadcounter($alldownloadcounter)
{
$this->alldownloadcounter = $alldownloadcounter;
}
/**
* @return int
*/
public function getAlldownloadcounter()
{
return $this->alldownloadcounter;
}
}
@@ -0,0 +1,119 @@
<?php
namespace TYPO3\CMS\Extensionmanager\Domain\Model;
/*
* 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!
*/
/**
* Repository mirrors object for extension manager.
* @internal This class is a specific domain model implementation and is not part of the Public TYPO3 API.
*/
class Mirrors extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* Keeps mirrors.
*
* @var array
*/
protected $mirrors = [];
/**
* Keeps currently select mirror.
*
* Is array index.
*
* @var int
*/
protected $currentMirror;
/**
* Keeps information if a mirror should
* be randomly selected.
*
* @var bool
*/
protected $isRandomSelection = true;
/**
* Method selects one specific mirror to be used.
*
* @param int $mirrorId number (>=1) of mirror or NULL for random selection
* @see $currentMirror
*/
public function setSelect($mirrorId = null)
{
if ($mirrorId === null) {
$this->isRandomSelection = true;
} else {
if (is_int($mirrorId) && $mirrorId >= 1 && $mirrorId <= count($this->mirrors)) {
$this->currentMirror = $mirrorId - 1;
}
}
}
/**
* Method returns one mirror for use.
*
* Mirror has previously been selected or is chosen
* randomly.
*
* @return array array of a mirror's properties or NULL in case of errors
*/
public function getMirror()
{
$sumMirrors = count($this->mirrors);
if ($sumMirrors > 0) {
if (!is_int($this->currentMirror)) {
$this->currentMirror = rand(0, $sumMirrors - 1);
}
return $this->mirrors[$this->currentMirror];
}
return null;
}
/**
* Gets the mirror url from selected mirror
*
* @return string
*/
public function getMirrorUrl()
{
$mirror = $this->getMirror();
$mirrorUrl = $mirror['host'] . $mirror['path'];
return 'https://' . $mirrorUrl;
}
/**
* Method returns all available mirrors.
*
* @return array multidimensional array with mirrors and their properties
* @see $mirrors, setMirrors()
*/
public function getMirrors()
{
return $this->mirrors;
}
/**
* Method sets available mirrors.
*
* @param array $mirrors multidimensional array with mirrors and their properties
* @see $mirrors, getMirrors()
*/
public function setMirrors(array $mirrors)
{
if (count($mirrors) >= 1) {
$this->mirrors = $mirrors;
}
}
}
@@ -0,0 +1,258 @@
<?php
namespace TYPO3\CMS\Extensionmanager\Domain\Model;
/*
* 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!
*/
/**
* Repository object for extension manager.
* @internal This class is a specific domain model implementation and is not part of the Public TYPO3 API.
*/
class Repository extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* Keeps repository title.
*
* @var string
*/
protected $title;
/**
* Keeps repository description.
*
* @var string
*/
protected $description;
/**
* Keeps mirror list URL.
*
* @var string
*/
protected $mirrorListUrl;
/**
* Keeps repository mirrors object.
*
* @var \TYPO3\CMS\Extensionmanager\Domain\Model\Mirrors
*/
protected $mirrors;
/**
* Keeps wsdl URL.
*
* @var string
*/
protected $wsdlUrl;
/**
* Keeps last update.
*
* @var \DateTime
*/
protected $lastUpdate;
/**
* Keeps extension count.
*
* @var string
*/
protected $extensionCount;
/**
* Method returns title of a repository.
*
* @return string title of repository
* @see $title, setTitle()
*/
public function getTitle()
{
return $this->title;
}
/**
* Method sets title of a repository.
*
* @param string $title title of repository to set
* @see $title, getTitle()
*/
public function setTitle($title)
{
if (!empty($title) && is_string($title)) {
$this->title = $title;
}
}
/**
* Method returns description of a repository.
*
* @return string title of repository
* @see $title, setTitle()
*/
public function getDescription()
{
return $this->description;
}
/**
* Method sets description of a repository.
*
* @param string $description title of repository to set
*/
public function setDescription($description)
{
if (!empty($description) && is_string($description)) {
$this->description = $description;
}
}
/**
* Method returns URL of a resource that contains repository mirrors.
*
* @return string URL of file that contains repository mirrors
* @see $mirrorListUrl, getMirrorListUrl()
*/
public function getMirrorListUrl()
{
return $this->mirrorListUrl;
}
/**
* Method sets URL of a resource that contains repository mirrors.
*
* Parameter is typically a remote gzipped xml file.
*
* @param string $url URL of file that contains repository mirrors
* @see $mirrorListUrl, getMirrorListUrl()
*/
public function setMirrorListUrl($url)
{
if (empty($url) || !empty($url) && \TYPO3\CMS\Core\Utility\GeneralUtility::isValidUrl($url)) {
$this->mirrorListUrl = $url;
}
}
/**
* Method returns URL of repository WSDL.
*
* @return string URL of repository WSDL
* @see $wsdlUrl, setWsdlUrl()
*/
public function getWsdlUrl()
{
return $this->wsdlUrl;
}
/**
* Method sets URL of repository WSDL.
*
* @param string $url URL of repository WSDL
* @see $wsdlUrl, getWsdlUrl()
*/
public function setWsdlUrl($url)
{
if (!empty($url) && \TYPO3\CMS\Core\Utility\GeneralUtility::isValidUrl($url)) {
$this->wsdlUrl = $url;
}
}
/**
* Method returns LastUpdate.
*
* @return \DateTime timestamp of last update
*/
public function getLastUpdate()
{
return $this->lastUpdate;
}
/**
* Method sets LastUpdate.
*
* @param \DateTime $time URL of repository WSDL
*/
public function setLastUpdate(\DateTime $time)
{
$this->lastUpdate = $time;
}
/**
* Method returns extension count
*
* @return int count of read extensions
*/
public function getExtensionCount()
{
return $this->extensionCount;
}
/**
* Method sets extension count
*
* @param string $count count of read extensions
*/
public function setExtensionCount($count)
{
$this->extensionCount = $count;
}
/**
* Method registers repository mirrors object.
*
* Repository mirrors object is passed by reference.
*
* @param \TYPO3\CMS\Extensionmanager\Domain\Model\Mirrors $mirrors mirror list
* @see $mirrors, getMirrors(), hasMirrors(), removeMirrors()
*/
public function addMirrors(\TYPO3\CMS\Extensionmanager\Domain\Model\Mirrors $mirrors)
{
$this->mirrors = $mirrors;
}
/**
* Method returns information if a repository mirrors
* object has been registered to this repository.
*
* @return bool TRUE, if a repository mirrors object has been registered, otherwise FALSE
* @see $mirrors, addMirrors(), getMirrors(), removeMirrors()
*/
public function hasMirrors()
{
$hasMirrors = false;
if (is_object($this->mirrors)) {
$hasMirrors = true;
}
return $hasMirrors;
}
/**
* Method returns a repository mirrors object.
*
* @return \TYPO3\CMS\Extensionmanager\Domain\Model\Mirrors mirrors for repository
* @see $mirrors, addMirrors(), hasMirrors(), removeMirrors()
*/
public function getMirrors()
{
return $this->hasMirrors() ? $this->mirrors : null;
}
/**
* Method unregisters a repository mirrors object.
*
* @see $mirrors, addMirrors(), getMirrors(), hasMirrors()
*/
public function removeMirrors()
{
unset($this->mirrors);
}
}
@@ -0,0 +1,439 @@
<?php
namespace TYPO3\CMS\Extensionmanager\Domain\Repository;
/*
* 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!
*/
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Platform\PlatformInformation;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* A repository for extensions
* @internal This class is a specific domain repository implementation and is not part of the Public TYPO3 API.
*/
class ExtensionRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
/**
* @var string
*/
const TABLE_NAME = 'tx_extensionmanager_domain_model_extension';
/**
* Do not include pid in queries
*/
public function initializeObject()
{
/** @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings */
$defaultQuerySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class);
$defaultQuerySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($defaultQuerySettings);
}
/**
* Count all extensions
*
* @return int
*/
public function countAll()
{
$query = $this->createQuery();
$query = $this->addDefaultConstraints($query);
return $query->execute()->count();
}
/**
* Finds all extensions
*
* @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findAll()
{
$query = $this->createQuery();
$query = $this->addDefaultConstraints($query);
$query->setOrderings(
[
'lastUpdated' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
]
);
return $query->execute();
}
/**
* Find an extension by extension key ordered by version
*
* @param string $extensionKey
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findByExtensionKeyOrderedByVersion($extensionKey)
{
$query = $this->createQuery();
$query->matching($query->logicalAnd($query->equals('extensionKey', $extensionKey), $query->greaterThanOrEqual('reviewState', 0)));
$query->setOrderings(['integerVersion' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING]);
return $query->execute();
}
/**
* Find the current version by extension key
*
* @param string $extensionKey
* @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findOneByCurrentVersionByExtensionKey($extensionKey)
{
$query = $this->createQuery();
$query->matching(
$query->logicalAnd(
$query->equals('extensionKey', $extensionKey),
$query->greaterThanOrEqual('reviewState', 0),
$query->equals('currentVersion', 1)
)
);
$query->setLimit(1);
return $query->execute()->getFirst();
}
/**
* Find one extension by extension key and version
*
* @param string $extensionKey
* @param string $version (example: 4.3.10)
* @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findOneByExtensionKeyAndVersion($extensionKey, $version)
{
$query = $this->createQuery();
// Hint: This method must not filter out insecure extensions, if needed,
// it should be done on a different level, or with a helper method.
$query->matching($query->logicalAnd(
$query->equals('extensionKey', $extensionKey),
$query->equals('version', $version)
));
return $query->setLimit(1)->execute()->getFirst();
}
/**
* Find an extension by title, author name or extension key
* This is the function used by the TER search. It is using a
* scoring for the matches to sort the extension with an
* exact key match on top
*
* @param string $searchString The string to search for extensions
* @return mixed
*/
public function findByTitleOrAuthorNameOrExtensionKey($searchString)
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable(self::TABLE_NAME);
$searchPlaceholderForLike = '%' . $queryBuilder->escapeLikeWildcards($searchString) . '%';
$searchConstraints = [
'extension_key' => $queryBuilder->expr()->eq(
'extension_key',
$queryBuilder->createNamedParameter($searchString, \PDO::PARAM_STR)
),
'extension_key_like' => $queryBuilder->expr()->like(
'extension_key',
$queryBuilder->createNamedParameter($searchPlaceholderForLike, \PDO::PARAM_STR)
),
'title' => $queryBuilder->expr()->like(
'title',
$queryBuilder->createNamedParameter($searchPlaceholderForLike, \PDO::PARAM_STR)
),
'description' => $queryBuilder->expr()->like(
'description',
$queryBuilder->createNamedParameter($searchPlaceholderForLike, \PDO::PARAM_STR)
),
'author_name' => $queryBuilder->expr()->like(
'author_name',
$queryBuilder->createNamedParameter($searchPlaceholderForLike, \PDO::PARAM_STR)
),
];
$caseStatement = 'CASE ' .
'WHEN ' . $searchConstraints['extension_key'] . ' THEN 16 ' .
'WHEN ' . $searchConstraints['extension_key_like'] . ' THEN 8 ' .
'WHEN ' . $searchConstraints['title'] . ' THEN 4 ' .
'WHEN ' . $searchConstraints['description'] . ' THEN 2 ' .
'WHEN ' . $searchConstraints['author_name'] . ' THEN 1 ' .
'END AS ' . $queryBuilder->quoteIdentifier('position');
$result = $queryBuilder
->select('*')
->addSelectLiteral($caseStatement)
->from(self::TABLE_NAME)
->where(
$queryBuilder->expr()->orX(...array_values($searchConstraints)),
$queryBuilder->expr()->eq('current_version', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)),
$queryBuilder->expr()->gte('review_state', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
)
->orderBy('position', 'DESC')
->execute()
->fetchAll();
$dataMapper = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
return $dataMapper->map(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, $result);
}
/**
* Find an extension between a certain version range ordered by version number
*
* @param string $extensionKey
* @param int $lowestVersion
* @param int $highestVersion
* @param bool $includeCurrentVersion
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findByVersionRangeAndExtensionKeyOrderedByVersion($extensionKey, $lowestVersion = 0, $highestVersion = 0, $includeCurrentVersion = true)
{
$query = $this->createQuery();
$constraint = null;
if ($lowestVersion !== 0 && $highestVersion !== 0) {
if ($includeCurrentVersion) {
$constraint = $query->logicalAnd($query->lessThanOrEqual('integerVersion', $highestVersion), $query->greaterThanOrEqual('integerVersion', $lowestVersion), $query->equals('extensionKey', $extensionKey));
} else {
$constraint = $query->logicalAnd($query->lessThanOrEqual('integerVersion', $highestVersion), $query->greaterThan('integerVersion', $lowestVersion), $query->equals('extensionKey', $extensionKey));
}
} elseif ($lowestVersion === 0 && $highestVersion !== 0) {
if ($includeCurrentVersion) {
$constraint = $query->logicalAnd($query->lessThanOrEqual('integerVersion', $highestVersion), $query->equals('extensionKey', $extensionKey));
} else {
$constraint = $query->logicalAnd($query->lessThan('integerVersion', $highestVersion), $query->equals('extensionKey', $extensionKey));
}
} elseif ($lowestVersion !== 0 && $highestVersion === 0) {
if ($includeCurrentVersion) {
$constraint = $query->logicalAnd($query->greaterThanOrEqual('integerVersion', $lowestVersion), $query->equals('extensionKey', $extensionKey));
} else {
$constraint = $query->logicalAnd($query->greaterThan('integerVersion', $lowestVersion), $query->equals('extensionKey', $extensionKey));
}
} elseif ($lowestVersion === 0 && $highestVersion === 0) {
$constraint = $query->equals('extensionKey', $extensionKey);
}
if ($constraint) {
$query->matching($query->logicalAnd($constraint, $query->greaterThanOrEqual('reviewState', 0)));
}
$query->setOrderings([
'integerVersion' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
]);
return $query->execute();
}
/**
* Finds all extensions with category "distribution" not published by the TYPO3 CMS Team
*
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findAllCommunityDistributions()
{
$query = $this->createQuery();
$query->matching(
$query->logicalAnd(
$query->equals('category', \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::DISTRIBUTION_CATEGORY),
$query->logicalNot($query->equals('ownerusername', 'typo3v4'))
)
);
$query->setOrderings([
'alldownloadcounter' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
]);
return $query->execute();
}
/**
* Finds all extensions with category "distribution" that are published by the TYPO3 CMS Team
*
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findAllOfficialDistributions()
{
$query = $this->createQuery();
$query->matching(
$query->logicalAnd(
$query->equals('category', \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::DISTRIBUTION_CATEGORY),
$query->equals('ownerusername', 'typo3v4')
)
);
$query->setOrderings([
'alldownloadcounter' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
]);
return $query->execute();
}
/**
* Count extensions with a certain key between a given version range
*
* @param string $extensionKey
* @param int $lowestVersion
* @param int $highestVersion
* @return int
*/
public function countByVersionRangeAndExtensionKey($extensionKey, $lowestVersion = 0, $highestVersion = 0)
{
return $this->findByVersionRangeAndExtensionKeyOrderedByVersion($extensionKey, $lowestVersion, $highestVersion)->count();
}
/**
* Find highest version available of an extension
*
* @param string $extensionKey
* @return \TYPO3\CMS\Extensionmanager\Domain\Model\Extension
*/
public function findHighestAvailableVersion($extensionKey)
{
$query = $this->createQuery();
$query->matching($query->logicalAnd($query->equals('extensionKey', $extensionKey), $query->greaterThanOrEqual('reviewState', 0)));
$query->setOrderings([
'integerVersion' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
]);
return $query->setLimit(1)->execute()->getFirst();
}
/**
* Updates the current_version field after update.
*
* @param int $repositoryUid
* @return int
*/
public function insertLastVersion($repositoryUid = 1)
{
$this->markExtensionWithMaximumVersionAsCurrent($repositoryUid);
return $this->getNumberOfCurrentExtensions();
}
/**
* Sets current_version = 1 for all extensions where the extension version is maximal.
*
* For performance reasons, the "native" database connection is used here directly.
*
* @param int $repositoryUid
*/
protected function markExtensionWithMaximumVersionAsCurrent($repositoryUid)
{
$uidsOfCurrentVersion = $this->fetchMaximalVersionsForAllExtensions($repositoryUid);
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable(self::TABLE_NAME);
$connection = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable(self::TABLE_NAME);
$maxBindParameters = PlatformInformation::getMaxBindParameters(
$connection->getDatabasePlatform()
);
foreach (array_chunk($uidsOfCurrentVersion, $maxBindParameters - 10) as $chunk) {
$queryBuilder
->update(self::TABLE_NAME)
->where(
$queryBuilder->expr()->in(
'uid',
$queryBuilder->createNamedParameter($chunk, Connection::PARAM_INT_ARRAY)
)
)
->set('current_version', 1)
->execute();
}
}
/**
* Fetches the UIDs of all maximal versions for all extensions.
* This is done by doing a LEFT JOIN to itself ("a" and "b") and comparing
* both integer_version fields.
*
* @param int $repositoryUid
* @return array
*/
protected function fetchMaximalVersionsForAllExtensions($repositoryUid)
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable(self::TABLE_NAME);
$queryResult = $queryBuilder
->select('a.uid AS uid')
->from(self::TABLE_NAME, 'a')
->leftJoin(
'a',
self::TABLE_NAME,
'b',
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('a.repository', $queryBuilder->quoteIdentifier('b.repository')),
$queryBuilder->expr()->eq('a.extension_key', $queryBuilder->quoteIdentifier('b.extension_key')),
$queryBuilder->expr()->lt('a.integer_version', $queryBuilder->quoteIdentifier('b.integer_version'))
)
)
->where(
$queryBuilder->expr()->eq(
'a.repository',
$queryBuilder->createNamedParameter($repositoryUid, \PDO::PARAM_INT)
),
$queryBuilder->expr()->isNull('b.extension_key')
)
->orderBy('a.uid')
->execute();
$extensionUids = [];
while ($row = $queryResult->fetch()) {
$extensionUids[] = $row['uid'];
}
return $extensionUids;
}
/**
* Returns the number of extensions that are current.
*
* @return int
*/
protected function getNumberOfCurrentExtensions()
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable(self::TABLE_NAME);
return (int)$queryBuilder
->count('*')
->from(self::TABLE_NAME)
->where($queryBuilder->expr()->eq(
'current_version',
$queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)
))
->execute()
->fetchColumn(0);
}
/**
* Adds default constraints to the query - in this case it
* enables us to always just search for the latest version of an extension
*
* @param \TYPO3\CMS\Extbase\Persistence\Generic\Query $query the query to adjust
* @return \TYPO3\CMS\Extbase\Persistence\Generic\Query
*/
protected function addDefaultConstraints(\TYPO3\CMS\Extbase\Persistence\Generic\Query $query)
{
if ($query->getConstraint()) {
$query->matching($query->logicalAnd(
$query->getConstraint(),
$query->equals('current_version', true),
$query->greaterThanOrEqual('reviewState', 0)
));
} else {
$query->matching($query->logicalAnd(
$query->equals('current_version', true),
$query->greaterThanOrEqual('reviewState', 0)
));
}
return $query;
}
}
@@ -0,0 +1,68 @@
<?php
namespace TYPO3\CMS\Extensionmanager\Domain\Repository;
/*
* 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!
*/
/**
* A repository for extension repositories
* @internal This class is a specific domain repository implementation and is not part of the Public TYPO3 API.
*/
class RepositoryRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
/**
* Do not include pid in queries
*/
public function initializeObject()
{
/** @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings */
$defaultQuerySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class);
$defaultQuerySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($defaultQuerySettings);
}
/**
* Updates ExtCount and lastUpdated in Repository eg after import
*
* @param int $extCount
* @param int $uid
*/
public function updateRepositoryCount($extCount, $uid = 1)
{
$repository = $this->findByUid($uid);
$repository->setLastUpdate(new \DateTime());
$repository->setExtensionCount((int)$extCount);
$this->update($repository);
}
/**
* Find main typo3.org repository
*
* @return \TYPO3\CMS\Extensionmanager\Domain\Model\Repository
*/
public function findOneTypo3OrgRepository()
{
$allRepositories = $this->findAll();
$typo3OrgRepository = null;
foreach ($allRepositories as $repository) {
/** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Repository $repository */
if ($repository->getTitle() === 'TYPO3.org Main Repository') {
$typo3OrgRepository = $repository;
break;
}
}
return $typo3OrgRepository;
}
}