Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
services
t3o sites
extensions.typo3.org
extensions.typo3.org
Commits
1ab7b9af
Commit
1ab7b9af
authored
Aug 16, 2020
by
Thomas Löffler
Browse files
Create new command to check outdated extension versions
parent
0667d169
Pipeline
#9452
failed with stages
in 3 minutes and 38 seconds
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
extensions/ter_fe2/Classes/Command/CheckForOutdatedExtensions.php
0 → 100644
View file @
1ab7b9af
<?php
declare
(
strict_types
=
1
);
namespace
T3o\TerFe2\Command
;
/*
* This file is part of a TYPO3 extension.
*
* 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
Symfony\Component\Console\Command\Command
;
use
Symfony\Component\Console\Input\InputInterface
;
use
Symfony\Component\Console\Output\OutputInterface
;
use
Symfony\Component\Console\Style\SymfonyStyle
;
use
T3o\TerFe2\Domain\Repository\CombinedExtensionRepository
;
use
TYPO3\CMS\Core\Database\ConnectionPool
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
class
CheckForOutdatedExtensions
extends
Command
implements
\
Psr\Log\LoggerAwareInterface
{
use
\
Psr\Log\LoggerAwareTrait
;
/**
* @var CombinedExtensionRepository
*/
protected
$combinedExtensionRepository
;
public
function
__construct
(
string
$name
=
null
,
CombinedExtensionRepository
$combinedExtensionRepository
=
null
)
{
$this
->
combinedExtensionRepository
=
$combinedExtensionRepository
??
GeneralUtility
::
makeInstance
(
CombinedExtensionRepository
::
class
);
parent
::
__construct
(
$name
);
}
protected
function
configure
()
{
$this
->
setDescription
(
'Checks all versions if they are outdated (not supporting an actively supported TYPO3 CMS version).'
);
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected
function
execute
(
InputInterface
$input
,
OutputInterface
$output
)
{
$io
=
new
SymfonyStyle
(
$input
,
$output
);
$io
->
section
(
'Fetching not outdated and not insecure versions'
);
$versions
=
$this
->
getAllNonOutdatedAndNotInsecureVersions
();
$io
->
success
(
'Found '
.
count
(
$versions
)
.
' versions to check.'
);
$outdatedVersions
=
0
;
if
(
$versions
)
{
$progressBar
=
new
\
Symfony\Component\Console\Helper\ProgressBar
(
$output
,
count
(
$versions
));
$progressBar
->
setFormat
(
'very_verbose'
);
$outdatedVersionService
=
GeneralUtility
::
makeInstance
(
\
T3o\TerFe2\Service\OutdatedVersionService
::
class
);
$io
->
section
(
'Checking versions...'
);
$progressBar
->
start
();
foreach
(
$versions
as
$version
)
{
[
$minimumVersion
,
$maximumVersion
]
=
$this
->
getTypo3Dependency
(
$version
[
'uid'
]);
if
(
!
$outdatedVersionService
->
isVersionDependingOnAnActiveSupportedTypo3Version
(
$minimumVersion
,
$maximumVersion
))
{
$this
->
setVersionAsOutdated
(
$version
[
'uid'
]);
$outdatedVersions
++
;
}
$progressBar
->
advance
();
}
$progressBar
->
finish
();
$io
->
writeln
(
''
);
}
$io
->
success
(
'Set '
.
$outdatedVersions
.
' versions as outdated'
);
}
protected
function
getAllNonOutdatedAndNotInsecureVersions
():
?array
{
$queryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getQueryBuilderForTable
(
'tx_terfe2_domain_model_version'
);
$queryBuilder
->
getRestrictions
()
->
removeAll
();
return
$queryBuilder
->
select
(
'uid'
)
->
from
(
'tx_terfe2_domain_model_version'
)
->
where
(
$queryBuilder
->
expr
()
->
eq
(
'deleted'
,
0
),
$queryBuilder
->
expr
()
->
eq
(
'hidden'
,
0
),
$queryBuilder
->
expr
()
->
gte
(
'review_state'
,
0
)
)
->
orderBy
(
'upload_date'
,
'ASC'
)
->
execute
()
->
fetchAll
(
\
PDO
::
FETCH_ASSOC
);
}
protected
function
getTypo3Dependency
(
int
$versionUid
):
array
{
$queryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getQueryBuilderForTable
(
'tx_terfe2_domain_model_relation'
);
$queryBuilder
->
getRestrictions
()
->
removeAll
();
$typo3Dependency
=
$queryBuilder
->
select
(
...
[
'minimum_version'
,
'maximum_version'
])
->
from
(
'tx_terfe2_domain_model_relation'
)
->
where
(
$queryBuilder
->
expr
()
->
eq
(
'deleted'
,
0
),
$queryBuilder
->
expr
()
->
eq
(
'hidden'
,
0
),
$queryBuilder
->
expr
()
->
eq
(
'relation_key'
,
$queryBuilder
->
createNamedParameter
(
'typo3'
)),
$queryBuilder
->
expr
()
->
eq
(
'version'
,
$versionUid
)
)
->
execute
()
->
fetch
(
\
PDO
::
FETCH_ASSOC
);
return
[
$typo3Dependency
[
'minimum_version'
],
$typo3Dependency
[
'maximum_version'
],
];
}
protected
function
setVersionAsOutdated
(
int
$versionUid
)
{
$queryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getQueryBuilderForTable
(
'tx_terfe2_domain_model_version'
);
$queryBuilder
->
update
(
'tx_terfe2_domain_model_version'
)
->
set
(
'review_state'
,
-
2
)
->
where
(
$queryBuilder
->
expr
()
->
eq
(
'uid'
,
$versionUid
))
->
execute
();
}
}
extensions/ter_fe2/Classes/Service/OutdatedVersionService.php
0 → 100644
View file @
1ab7b9af
<?php
declare
(
strict_types
=
1
);
namespace
T3o\TerFe2\Service
;
/*
* This file is part of a TYPO3 extension.
*
* 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\Utility\GeneralUtility
;
class
OutdatedVersionService
{
public
$supportedCoreVersions
=
[];
public
function
__construct
()
{
$this
->
supportedCoreVersions
=
GeneralUtility
::
makeInstance
(
LTSVersionService
::
class
)
->
getActiveVersions
();
}
/**
* Checks if the version range of an extension is currently
* supported by one of the active TYPO3 CMS core versions.
*
* @param int $minimumExtensionVersion
* @param int $maximumExtensionVersion
* @return bool
*/
public
function
isVersionDependingOnAnActiveSupportedTypo3Version
(
int
$minimumExtensionVersion
,
int
$maximumExtensionVersion
):
bool
{
foreach
(
$this
->
supportedCoreVersions
as
$supportedCoreFirstVersion
)
{
$minimumCoreVersion
=
$supportedCoreFirstVersion
;
$maximumCoreVersion
=
$supportedCoreFirstVersion
+
999
;
if
(
$minimumExtensionVersion
>=
$minimumCoreVersion
&&
$minimumExtensionVersion
<
$maximumCoreVersion
)
{
return
true
;
}
if
(
$maximumExtensionVersion
>=
$minimumCoreVersion
&&
$maximumExtensionVersion
<
$maximumCoreVersion
)
{
return
true
;
}
if
(
$minimumExtensionVersion
<
$minimumCoreVersion
&&
$maximumExtensionVersion
>
$maximumCoreVersion
)
{
return
true
;
}
}
return
false
;
}
}
extensions/ter_fe2/Classes/Task/CheckForOutdatedExtensions.php
deleted
100644 → 0
View file @
0667d169
<?php
namespace
T3o\TerFe2\Task
;
/*
* 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
ApacheSolrForTypo3\Solr\IndexQueue\Queue
;
use
Psr\Log\LoggerInterface
;
use
TYPO3\CMS\Core\Core\Environment
;
use
TYPO3\CMS\Core\Database\ConnectionPool
;
use
TYPO3\CMS\Core\Log\LogManager
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
use
TYPO3\CMS\Core\Utility\VersionNumberUtility
;
use
TYPO3\CMS\Extbase\Object\ObjectManager
;
use
TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
;
use
TYPO3\CMS\Extbase\Persistence\Generic\Session
;
use
TYPO3\CMS\Extbase\Scheduler\Task
;
/**
* Class CheckForOutdatedExtensions
*/
class
CheckForOutdatedExtensions
extends
Task
{
/**
* @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
*/
protected
$persistenceManager
;
/**
* @var \T3o\TerFe2\Domain\Repository\VersionRepository
*/
protected
$versionRepository
;
/**
* @var array
*/
protected
$coreVersions
;
/**
* @var \TYPO3\CMS\Extbase\Object\ObjectManager
*/
protected
$objectManager
;
/**
* @var \TYPO3\CMS\Extbase\Persistence\Generic\Session
*/
protected
$session
;
/**
* @var array
*/
protected
$supportedCoreVersions
=
[];
/**
* @var int
*/
protected
$releaseDateOfOldestSupportedTypo3Version
;
/**
* @var \ApacheSolrForTypo3\Solr\IndexQueue\Queue
*/
protected
$solrIndexQueue
;
/**
* @var LoggerInterface
*/
protected
$logger
;
/**
* Initialize Task
*/
public
function
initializeTask
()
{
$this
->
objectManager
=
GeneralUtility
::
makeInstance
(
ObjectManager
::
class
);
$this
->
persistenceManager
=
$this
->
objectManager
->
get
(
PersistenceManager
::
class
);
$this
->
session
=
$this
->
objectManager
->
get
(
Session
::
class
);
$this
->
versionRepository
=
$this
->
objectManager
->
get
(
\
T3o\TerFe2\Domain\Repository\VersionRepository
::
class
);
$this
->
coreVersions
=
json_decode
(
GeneralUtility
::
getURL
(
Environment
::
getPublicPath
()
.
'/'
.
$GLOBALS
[
'TYPO3_CONF_VARS'
][
'BE'
][
'fileadminDir'
]
.
'currentcoredata.json'
),
true
);
$this
->
solrIndexQueue
=
$this
->
objectManager
->
get
(
Queue
::
class
);
}
/**
* Execute Task
*
* @return bool
*/
public
function
execute
()
{
$this
->
logger
=
GeneralUtility
::
makeInstance
(
LogManager
::
class
)
->
getLogger
(
__CLASS__
);
$this
->
logger
->
info
(
'Task CheckForOutdatedExtensions started'
);
$this
->
initializeTask
();
// Find all extension versions which are not outdated.
$versions
=
$this
->
getNotOutdatedAndSecureVersions
();
$this
->
getLatestAndOldestSupportedTypo3Versions
();
$this
->
releaseDateOfOldestSupportedTypo3Version
=
$this
->
getReleaseDateOfOldestSupportedTypo3Version
();
// Foreach extension
foreach
(
$versions
as
$version
)
{
$this
->
checkVersion
(
$version
);
}
$this
->
logger
->
info
(
'Task CheckForOutdatedExtensions finished'
);
return
true
;
}
/**
* Get not outdated extensions
*
* @return mixed
*/
public
function
getNotOutdatedAndSecureVersions
()
{
$tableName
=
'tx_terfe2_domain_model_version'
;
$queryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getQueryBuilderForTable
(
$tableName
);
$queryBuilder
->
getRestrictions
()
->
removeAll
();
$statement
=
$queryBuilder
->
select
(
'uid'
)
->
from
(
$tableName
)
->
where
(
$queryBuilder
->
expr
()
->
eq
(
'deleted'
,
0
),
$queryBuilder
->
expr
()
->
eq
(
'hidden'
,
0
),
$queryBuilder
->
expr
()
->
gte
(
'review_state'
,
0
)
)
->
orderBy
(
'upload_date'
,
'ASC'
)
->
execute
();
$statement
->
execute
();
return
$statement
->
fetchAll
(
\
PDO
::
FETCH_ASSOC
);
}
/**
* Get the release date of the oldest supported TYPO3 Version.
*
* @return int
*/
public
function
getReleaseDateOfOldestSupportedTypo3Version
()
{
$oldestMinorVersion
=
explode
(
'.'
,
$this
->
supportedCoreVersions
[
'oldest'
]);
$oldestMinorVersion
=
$oldestMinorVersion
[
0
];
$releaseDate
=
$this
->
coreVersions
[
$oldestMinorVersion
][
'releases'
][
$this
->
supportedCoreVersions
[
'oldest'
]][
'date'
];
return
strtotime
(
$releaseDate
);
}
/**
* Get the latest and oldest supported TYPO3 Versions.
*
* @throws \RuntimeException
*/
public
function
getLatestAndOldestSupportedTypo3Versions
()
{
if
(
$this
->
coreVersions
===
null
)
{
throw
new
\
RuntimeException
(
'typo3.org JSON not accessible!'
,
1399140291
);
}
// Collect currently supported core versions
$oldestSupportedCoreVersion
=
'99.99.99'
;
$latestSupportedCoreVersion
=
'0.0.0'
;
$allSupportedCoreVersions
=
[];
foreach
(
$this
->
coreVersions
as
$version
=>
$coreInfo
)
{
// Only use keys that represent a branch number
if
(
preg_match
(
'/^\d+\.\d+$/'
,
$version
)
||
preg_match
(
'/^\d+$/'
,
$version
))
{
if
(
$coreInfo
[
'active'
]
===
true
)
{
$allSupportedCoreVersions
[]
=
$version
;
// Checks the latest version
$latestBranchVersion
=
$coreInfo
[
'latest'
];
if
(
!
preg_match
(
'/dev|alpha/'
,
$latestBranchVersion
))
{
if
(
version_compare
(
$latestSupportedCoreVersion
,
$latestBranchVersion
,
'<'
))
{
$latestSupportedCoreVersion
=
$latestBranchVersion
;
}
}
// Check the oldest active version
if
(
version_compare
(
$version
.
'.0'
,
$oldestSupportedCoreVersion
,
'<'
))
{
$oldestSupportedCoreVersion
=
$version
;
}
}
}
}
// get first beta of oldest active version
$oldestSupportedCoreVersionReleases
=
array_reverse
(
$this
->
coreVersions
[
$oldestSupportedCoreVersion
][
'releases'
]);
foreach
(
$oldestSupportedCoreVersionReleases
as
$subVersion
=>
$subVersionInfo
)
{
if
(
!
preg_match
(
'/dev|alpha/'
,
$subVersion
))
{
$oldestSupportedCoreVersion
=
$subVersion
;
break
;
}
}
$this
->
supportedCoreVersions
=
[
'latest'
=>
$latestSupportedCoreVersion
,
'oldest'
=>
$oldestSupportedCoreVersion
,
'all'
=>
$allSupportedCoreVersions
,
];
}
/**
* @param \T3o\TerFe2\Domain\Model\Relation $dependency
*
* @return bool
*/
public
function
isVersionDependingOnAnActiveSupportedTypo3Version
(
$dependency
)
{
$result
=
false
;
if
(
$dependency
instanceof
\
T3o\TerFe2\Domain\Model\Relation
)
{
$extensionMinimumVersion
=
$dependency
->
getMinimumVersion
();
$extensionMaximumVersion
=
$dependency
->
getMaximumVersion
();
foreach
(
$this
->
supportedCoreVersions
[
'all'
]
as
$version
)
{
$version
=
(
string
)
$version
;
// gets core version x.x.0
$supportedMinimumVersion
=
VersionNumberUtility
::
convertVersionNumberToInteger
(
$version
.
'.0'
);
$extensionMinimumVersionAsString
=
VersionNumberUtility
::
convertIntegerToVersionNumber
(
$extensionMinimumVersion
);
/*
* checks if extension dependency lies within the first release of the main release version
* or extension minimum version begins with main release version
*/
if
((
$supportedMinimumVersion
>=
$extensionMinimumVersion
||
strpos
(
$extensionMinimumVersionAsString
,
$version
)
===
0
)
&&
$supportedMinimumVersion
<=
$extensionMaximumVersion
)
{
$result
=
true
;
break
;
}
}
}
return
$result
;
}
/**
* check if the given version is outdated and mark it in database
*
* @param int $versionRecord
*/
protected
function
checkVersion
(
$versionRecord
)
{
/** @var \T3o\TerFe2\Domain\Model\Version $version */
$version
=
$this
->
versionRepository
->
findByUid
(
$versionRecord
[
'uid'
]);
if
(
!
$version
instanceof
\
T3o\TerFe2\Domain\Model\Version
)
{
return
;
}
$isOutdated
=
false
;
if
(
$version
->
getUploadDate
()
===
null
)
{
$isOutdated
=
true
;
// Check if date is set
}
elseif
(
$version
->
getUploadDate
()
<
$this
->
releaseDateOfOldestSupportedTypo3Version
)
{
$isOutdated
=
true
;
// Check upload date against oldestActiveTYPO3Version first release date.
}
elseif
(
!
$this
->
isVersionDependingOnAnActiveSupportedTypo3Version
(
$version
->
getTypo3Dependency
()))
{
$isOutdated
=
true
;
// Check against dependency against TYPO3 not actively supported
}
if
(
$isOutdated
)
{
$connectionPool
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
);
$queryBuilder
=
$connectionPool
->
getQueryBuilderForTable
(
'tx_terfe2_domain_model_version'
);
$queryBuilder
->
update
(
'tx_terfe2_domain_model_version'
)
->
set
(
'review_state'
,
-
2
)
->
where
(
$queryBuilder
->
expr
()
->
eq
(
'uid'
,
$version
->
getUid
())
)
->
execute
();
if
(
$version
->
getExtension
()
&&
$version
->
getExtension
()
->
getUid
())
{
$queryBuilder
=
$connectionPool
->
getQueryBuilderForTable
(
'tx_terfe2_domain_model_extension'
);
$queryBuilder
->
update
(
'tx_terfe2_domain_model_extension'
)
->
set
(
'tstamp'
,
time
())
->
where
(
$queryBuilder
->
expr
()
->
eq
(
'uid'
,
$version
->
getUid
())
)
->
execute
();
$this
->
solrIndexQueue
->
updateItem
(
'tx_terfe2_domain_model_extension'
,
$version
->
getExtension
()
->
getUid
());
}
}
$this
->
cleanupMemory
(
$version
);
}
/**
* free some memory after checking a version
*
* prevent memory leaks on the long running scheduler task
*
* @param \T3o\TerFe2\Domain\Model\Version $version
*/
public
function
cleanupMemory
(
$version
)
{
$this
->
session
->
unregisterReconstitutedEntity
(
$version
);
foreach
(
$version
->
getSoftwareRelations
()
as
$relation
)
{
/** @var $relation \T3o\TerFe2\Domain\Model\Relation */
$this
->
session
->
unregisterReconstitutedEntity
(
$relation
);
}
}
}
extensions/ter_fe2/Configuration/Commands.php
View file @
1ab7b9af
...
...
@@ -23,4 +23,7 @@ return [
'ter:fetchDocumentationStatus'
=>
[
'class'
=>
\
T3o\TerFe2\Command\FetchDocumentationStatus
::
class
],
'ter:checkForOutdatedExtensions'
=>
[
'class'
=>
\
T3o\TerFe2\Command\CheckForOutdatedExtensions
::
class
],
];
extensions/ter_fe2/Tests/Unit/
Task/CheckForOutdatedExtensions
Test.php
→
extensions/ter_fe2/Tests/Unit/
Service/OutdatedVersionService
Test.php
View file @
1ab7b9af
<?php
namespace
T3o\TerFe2\Tests\Unit\Task
;
declare
(
strict_types
=
1
);
namespace
T3o\TerFe2\Tests\Service
;
/*
******************************************************************
*
Copyright notice
/*
*
This file is part of a TYPO3 extension.
*
* (c) 2014 Thomas Löffler <thomas.loeffler@typo3.org>
* (c) 2014 Philipp Gampe <philipp.gampe@typo3.org>
* 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.
*
* All rights reserved
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
******************************************************************/
/**
* Class CheckForOutdatedExtensionsTest
*
* @author Thomas Löffler <loeffler@spooner-web.de>
* The TYPO3 project - inspiring people to share!
*/
class
CheckForOutdatedExtensionsTest
extends
\
Nimut\TestingFramework\TestCase\UnitTestCase
{
/**
* @var \T3o\TerFe2\Task\CheckForOutdatedExtensions
*/
protected
$subject
=
null
;
use
TYPO3\CMS\Core\Utility\VersionNumberUtility
;
class
OutdatedVersionServiceTest
extends
\
Nimut\TestingFramework\TestCase\AbstractTestCase
{