...
 
Commits (19)
solr/mycores/*
sequelpro.spf
db_snapshots
docker-compose.yaml
#ddev-generated: Automatically generated ddev .gitignore.
# You can remove the above line if you want to edit and maintain this file yourself.
/import.yaml
/docker-compose.yaml
/db_snapshots
/sequelpro.spf
/import-db
/.bgsync*
/config.*.y*ml
/.webimageExtra
/.dbimageExtra
/*-build/Dockerfile.example
APIVersion: v1.8.0
APIVersion: v1.9.1
name: ter
type: typo3
docroot: public
php_version: "7.2"
webserver_type: nginx-fpm
dbimage: drud/ddev-dbserver:v1.6.0-10.1
router_http_port: "80"
router_https_port: "443"
xdebug_enabled: false
......@@ -15,23 +14,22 @@ nfs_mount_enabled: false
provider: default
hooks:
post-start:
- exec: bash -c "sudo -E apt-get update"
- exec: bash -c "sudo -E apt-get install --yes --no-install-recommends apt-utils"
- exec: bash -c "sudo -E apt-get install --yes php7.2-ldap -o Dpkg::Options::=\"--force-confdef\"
-o Dpkg::Options::=\"--force-confold\" && killall -HUP php-fpm"
- exec: cp private/typo3conf/AdditionalConfiguration.ddev.php private/typo3conf/AdditionalConfiguration.php
- exec: composer install
- exec: npm --prefix private/typo3conf/ext/t3olayout/Build install
- exec: npm --prefix private/typo3conf/ext/t3olayout/Build run-script build
- exec: vendor/bin/typo3cms install:generatepackagestates
- exec: vendor/bin/typo3cms install:extensionsetupifpossible
webimage_extra_packages: [php7.2-ldap]
use_dns_when_possible: true
timezone: Europe/Berlin
# This config.yaml was created with ddev version v1.8.0
# webimage: drud/ddev-webserver:v1.8.0
# dbimage: drud/ddev-dbserver:v1.8.0-10.2
# dbaimage: drud/phpmyadmin:v1.8.0
# bgsyncimage: drud/ddev-bgsync:v1.8.0
# This config.yaml was created with ddev version v1.9.1
# webimage: drud/ddev-webserver:v1.9.0
# dbimage: drud/ddev-dbserver:v1.9.0-10.2
# dbaimage: drud/phpmyadmin:v1.9.0
# bgsyncimage: drud/ddev-bgsync:v1.9.0
# However we do not recommend explicitly wiring these images into the
# config.yaml as they may break future versions of ddev.
# You can update this config.yaml using 'ddev config'.
......@@ -39,7 +37,7 @@ hooks:
# Key features of ddev's config.yaml:
# name: <projectname> # Name of the project, automatically provides
# http://projectname.ddev.local and https://projectname.ddev.local
# http://projectname.ddev.site and https://projectname.ddev.site
# type: <projecttype> # drupal6/7/8, backdrop, typo3, wordpress, php
......@@ -66,8 +64,8 @@ hooks:
# additional_hostnames:
# - somename
# - someothername
# would provide http and https URLs for "somename.ddev.local"
# and "someothername.ddev.local".
# would provide http and https URLs for "somename.ddev.site"
# and "someothername.ddev.site".
# additional_fqdns:
# - example.com
......@@ -115,6 +113,12 @@ hooks:
# The host port binding for the ddev-dbserver can be explicitly specified. It is dynamic
# unless explicitly specified.
# phpmyadmin_port: "1000"
# The PHPMyAdmin port can be changed from the default 8036
# mailhog_port: "1001"
# The MailHog port can be changed from the default 8025
# webimage_extra_packages: [php-yaml, php7.3-ldap]
# Extra Debian packages that are needed in the webimage can be added here
# This is ignored if a free-form .ddev/web-build/Dockerfile is provided
......@@ -123,10 +127,26 @@ hooks:
# Extra Debian packages that are needed in the dbimage can be added here
# This is ignored if a free-form .ddev/db-build/Dockerfile is provided
# use_dns_when_possible: true
# If the host has internet access and the domain configured can
# successfully be looked up, DNS will be used for hostname resolution
# instead of editing /etc/hosts
# Defaults to true
# project_tld: ddev.site
# The top-level domain used for project URLs
# The default "ddev.site" allows DNS lookup via a wildcard
# For backward compatibility this can be changed to "ddev.local"
# ngrok_args: --subdomain mysite --auth "user:pass"
# Provide extra flags to the "ngrok http" command, see
# https://ngrok.com/docs#http or run "ngrok http -h"
# provider: default # Currently either "default" or "pantheon"
#
# Many ddev commands can be extended to run tasks after the ddev command is
# executed.
# Many ddev commands can be extended to run tasks before or after the
# ddev command is executed, for example "post-start", "post-import-db",
# "pre-composer", "post-composer"
# See https://ddev.readthedocs.io/en/stable/users/extending-commands/ for more
# information on the commands that can be extended and the tasks you can define
# for them. Example:
......
# You can copy this Dockerfile.example to Dockerfile to add configuration
# or packages or anything else to your dbimage
ARG BASE_IMAGE=drud/ddev-dbserver:v1.6.0-10.1
FROM $BASE_IMAGE
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y telnet netcat
RUN echo "Built from drud/ddev-dbserver:v1.6.0-10.1" >/var/tmp/built-from.txt
# You can copy this Dockerfile.example to Dockerfile to add configuration
# or packages or anything else to your webimage
ARG BASE_IMAGE=drud/ddev-webserver:v1.8.0
FROM $BASE_IMAGE
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y php-yaml
RUN npm install --global gulp-cli
RUN ln -fs /usr/share/zoneinfo/Europe/Berlin /etc/localtime && dpkg-reconfigure --frontend noninteractive tzdata
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# CSS-Files
[*.css]
indent_style = space
indent_size = 4
# HTML-Files
[*.html]
indent_style = space
indent_size = 4
# TMPL-Files
[*.tmpl]
indent_style = space
indent_size = 4
# SCSS-Files
[*.scss]
indent_style = space
indent_size = 4
# JS-Files
[*.js]
indent_style = space
indent_size = 4
# JSON-Files
[*.json]
indent_style = space
indent_size = 4
# PHP-Files
[*.php]
indent_style = space
indent_size = 4
# ReST-Files
[*.rst]
indent_style = space
indent_size = 3
# MD-Files
[*.md]
indent_style = space
indent_size = 4
# YAML-Files
[{*.yaml,*.yml}]
indent_style = space
indent_size = 2
# package.json
# .travis.yml
# bower.json
[{package.json,.travis.yml,bower.json}]
indent_style = space
indent_size = 4
# TypoScript
[*.ts]
indent_style = space
indent_size = 4
[*.typoscript]
indent_style = space
indent_size = 4
# XLF-Files
[*.xlf]
indent_style = space
indent_size = 4
# SQL-Files
[*.sql]
indent_style = space
indent_size = 2
This diff is collapsed.
......@@ -142,7 +142,7 @@ class tx_ter_helper
if ($row = $this->getDatabaseConnection()->sql_fetch_assoc($res)) {
if (!$this->userIsAlreadyLoggedIn(
$accountData
) && !$this->ldapValidationSucceeded($accountData)
) && !$this->ldapValidationSucceeded($accountData)
) {
throw new \T3o\Ter\Exception\UnauthorizedException('Wrong password.', TX_TER_ERROR_GENERAL_WRONGPASSWORD);
}
......
......@@ -615,4 +615,14 @@ class Extension extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
$this->notifications = $notifications;
}
public function getMatrixOfSupportedTypo3Versions(): array
{
$supportedTypo3Versions = [];
foreach ($this->versions as $version) {
$version->getMatrixOfSupportedTypo3Versions($supportedTypo3Versions);
}
return $supportedTypo3Versions;
}
}
......@@ -21,6 +21,8 @@ use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
*/
class Version extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
const VERSION_IS_INSECURE = -1;
const VERSION_IS_OUTDATED = -2;
/**
* Title of the extension
......@@ -1134,7 +1136,7 @@ class Version extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
}
/**
* @return \T3o\TerFe2\Domain\Model\Relation
* @return \T3o\TerFe2\Domain\Model\Relation|null
*/
public function getTypo3Dependency()
{
......@@ -1151,31 +1153,59 @@ class Version extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
}
/**
* @param array $supportedTypo3Versions
* @return array
*/
public function getMatrixOfSupportedTypo3Versions(): array
public function getMatrixOfSupportedTypo3Versions(array $supportedTypo3Versions = []): array
{
// @todo: Get these versions automatically
$typo3Versions = [
'7 LTS' => 7006000,
'8 LTS' => 8007000,
'9 LTS' => 9005000
];
$supportedTypo3Versions = [];
$ltsVersionService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\T3o\TerFe2\Service\LTSVersionService::class);
$oldLTSVersions = $ltsVersionService->getOldLTSVersions();
$this->getSupportedTypo3Versions($supportedTypo3Versions, $oldLTSVersions, 'warning');
foreach ($typo3Versions as $label => $mainVersion) {
$supportedTypo3Versions[$label] = \T3o\TerFe2\Utility\VersionUtility::doesExtensionSupportTypo3Version($this->getExtension(), $mainVersion);
$currentStableVersions = $ltsVersionService->getCurrentStableVersions(true);
$this->getSupportedTypo3Versions($supportedTypo3Versions, $currentStableVersions, 'success');
if ($this->doesSupportTypo3Version($ltsVersionService->getLatestDevelopmentVersion(true))) {
$supportedTypo3Versions[$ltsVersionService->getVersionLabelOfRelease($ltsVersionService->getLatestDevelopmentVersion(true))] = [
'label' => $ltsVersionService->getVersionLabelOfRelease($ltsVersionService->getLatestDevelopmentVersion(true)) . '-dev',
'badgeClass' => 'info'
];
}
return $supportedTypo3Versions;
}
/**
* @return bool
*/
public function hasTypo3Dependency()
public function doesSupportTypo3Version(int $versionNumber): bool
{
return $this->getTypo3Dependency() !== null;
if ($this->getTypo3Dependency() === null || $this->getReviewState() === \T3o\TerFe2\Domain\Model\Version::VERSION_IS_INSECURE) {
return false;
}
// reset from e.g. 7.6.21 to 7.6.0 for valid check
$resetMinimumVersion = (int)($this->getTypo3Dependency()->getMinimumVersion() / \T3o\TerFe2\Service\LTSVersionService::FACTOR_MINOR_VERSION) * \T3o\TerFe2\Service\LTSVersionService::FACTOR_MINOR_VERSION;
$supportsTypo3Version = $resetMinimumVersion <= $versionNumber && $this->getTypo3Dependency()->getMaximumVersion() >= $versionNumber;
if ($supportsTypo3Version) {
return true;
}
return false;
}
private function getSupportedTypo3Versions(array &$supportedTypo3Versions, array $versions, string $badgeClass)
{
$ltsVersionService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\T3o\TerFe2\Service\LTSVersionService::class);
foreach ($versions as $versionNumber) {
$mainVersion = floor($versionNumber / $ltsVersionService::FACTOR_MINOR_VERSION * $ltsVersionService::FACTOR_MINOR_VERSION);
$label = $ltsVersionService->getVersionLabelOfRelease($versionNumber) . ' LTS';
if ($this->doesSupportTypo3Version($mainVersion)) {
$supportedTypo3Versions[$ltsVersionService->getVersionLabelOfRelease($versionNumber)] = [
'label' => $label,
'badgeClass' => $badgeClass
];
}
}
}
/**
......
......@@ -43,7 +43,7 @@ class DocumentationService implements \TYPO3\CMS\Core\SingletonInterface
'pdf'
];
$documentationFile = PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . 'currentdocumentationdata.json';
$this->docsInformation = json_decode(file_get_contents($documentationFile));
$this->docsInformation = json_decode(file_get_contents($documentationFile), true);
}
/**
......@@ -60,16 +60,19 @@ class DocumentationService implements \TYPO3\CMS\Core\SingletonInterface
if (empty($extensionKey) || empty($versionString)) {
throw new \Exception('Extension key and version string are required to build a documentation url');
}
$url = '';
$documentationLink = '';
$oldManualsInformation = json_decode(@file_get_contents(PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . 'oldmanuals.json'), true);
$manualExists = isset($this->docsInformation->{$extensionKey}['docs'][$versionString]);
$documentationLink = null;
$url = null;
if ($manualExists) {
if (isset($this->docsInformation[$extensionKey]['docs'][$versionString])) {
// link to extension to get the latest manual
$url = $this->docsInformation->{$extensionKey}['docs'][$versionString]['url'];
// check if link is not broken
// need to remove the 200 response check due to change in header for docs.typo3.org
$url = $this->docsInformation[$extensionKey]['docs'][$versionString]['url'];
} elseif (isset($oldManualsInformation[$extensionKey])) {
$baseUrl = 'https://docs.typo3.org/typo3cms/extensions/';
$url = $baseUrl . $extensionKey . '/';
}
if ($url) {
$documentationLink = '<a href="' . $url . '">Extension Manual</a>';
}
......
......@@ -21,11 +21,20 @@ use TYPO3\CMS\Core\Utility\VersionNumberUtility;
*/
class LTSVersionService
{
const FACTOR_MAIN_VERSION = 1000000;
const FACTOR_MINOR_VERSION = 1000;
const FIRST_LTS_VERSION_WITH_MAIN_VERSION_NUMBER = 7;
/**
* @var array
*/
public $coreData = '';
public $ltsVersionsWithMinorVersions = [
'4.5',
'6.2'
];
public function __construct()
{
// Will be automatically update with UpdateCurrentVersionListTask see T3o\Ter\Task\UpdateCurrentVersionListTask
......@@ -37,28 +46,72 @@ class LTSVersionService
/**
* Get the current stable versions
*
* @param bool $fullVersionNumber
* @return array
*/
public function getCurrentStableVersions()
public function getCurrentStableVersions($fullVersionNumber = false): array
{
return [
$this->getLatestOldLTS(),
$this->getLatestLTS()
$this->getLatestOldLTS($fullVersionNumber),
$this->getLatestLTS($fullVersionNumber)
];
}
/**
* Returns all maintained versions.
*
* @param bool $fullVersionNumber
* @return array
*/
public function getAllMaintainedVersions()
public function getAllMaintainedVersions($fullVersionNumber = false): array
{
$versions = $this->getCurrentStableVersions();
array_push($versions, $this->getLatestDevelopmentVersion());
$versions = $this->getCurrentStableVersions($fullVersionNumber);
array_push($versions, $this->getLatestDevelopmentVersion($fullVersionNumber));
return $versions;
}
/**
* Get all LTS versions ever
*
* @return array
*/
public function getAllLTSVersions(): array
{
$ltsVersions = [];
foreach ($this->coreData as $releaseVersion => $releaseData) {
if (in_array($releaseVersion, $this->ltsVersionsWithMinorVersions) || $releaseVersion >= self::FIRST_LTS_VERSION_WITH_MAIN_VERSION_NUMBER) {
$latestVersionParts = explode('.', $releaseData['latest']);
if ((int)$latestVersionParts[1] === 0) {
continue;
}
$minimumVersion = $latestVersionParts[0] . '.' . $latestVersionParts[1] . '.0';
$ltsVersions[] = VersionNumberUtility::convertVersionNumberToInteger($minimumVersion);
}
}
sort($ltsVersions);
return $ltsVersions;
}
/**
* Get all LTS versions but current maintained
*
* @return array
*/
public function getOldLTSVersions(): array
{
$oldLTSVersions = $this->getAllLTSVersions();
foreach ($oldLTSVersions as $key => $version) {
$mainVersion = floor($version / self::FACTOR_MAIN_VERSION);
if (in_array($mainVersion, $this->getCurrentStableVersions())) {
unset($oldLTSVersions[$key]);
}
}
return $oldLTSVersions;
}
/**
* Get latest version within a specific release
*
......@@ -78,30 +131,57 @@ class LTSVersionService
/**
* Get latest development version
*
* @return string
* @param bool $fullVersionNumber
* @return int
*/
public function getLatestDevelopmentVersion()
public function getLatestDevelopmentVersion($fullVersionNumber = false): int
{
return substr($this->coreData['latest_stable'], 0, 3);
if ($fullVersionNumber) {
return VersionNumberUtility::convertVersionNumberToInteger($this->coreData['latest_stable']);
}
return floor(VersionNumberUtility::convertVersionNumberToInteger($this->coreData['latest_stable']) / self::FACTOR_MAIN_VERSION);
}
public function getVersionLabelOfRelease(int $release): string
{
if ($release >= (self::FIRST_LTS_VERSION_WITH_MAIN_VERSION_NUMBER * self::FACTOR_MAIN_VERSION)) {
$versionLabel = (string)floor($release / self::FACTOR_MAIN_VERSION);
} else {
$fullVersionLabelParts = explode('.', VersionNumberUtility::convertIntegerToVersionNumber($release));
$versionLabel = $fullVersionLabelParts[0] . '.' . $fullVersionLabelParts[1];
}
return $versionLabel;
}
/**
* Get latest LTS Version
*
* @param bool $fullVersionNumber
* @return int
*/
private function getLatestLTS()
public function getLatestLTS($fullVersionNumber = false): int
{
return (int)substr($this->coreData['latest_lts'], 0, 1);
if ($fullVersionNumber) {
return VersionNumberUtility::convertVersionNumberToInteger($this->coreData['latest_lts']);
}
return floor(VersionNumberUtility::convertVersionNumberToInteger($this->coreData['latest_lts']) / self::FACTOR_MAIN_VERSION);
}
/**
* Get latest "old" LTS Version
*
* @param bool $fullVersionNumber
* @return int
*/
private function getLatestOldLTS()
public function getLatestOldLTS($fullVersionNumber = false): int
{
return (int)substr($this->coreData['latest_old_lts'], 0, 1);
if ($fullVersionNumber) {
return VersionNumberUtility::convertVersionNumberToInteger($this->coreData['latest_old_lts']);
}
return floor(VersionNumberUtility::convertVersionNumberToInteger($this->coreData['latest_old_lts']) / self::FACTOR_MAIN_VERSION);
}
}
......@@ -15,6 +15,7 @@ namespace T3o\TerFe2\Solr\IndexQueue;
*/
use ApacheSolrForTypo3\Solr\IndexQueue\Item;
use ApacheSolrForTypo3\Solr\System\Solr\Document\Document;
use T3o\TerFe2\Utility\VersionUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
......@@ -55,14 +56,14 @@ class TerIndexer extends \ApacheSolrForTypo3\Solr\IndexQueue\Indexer
*
* @param Item $item An index queue item
* @param int $language Language Id
* @return \Apache_Solr_Document The Solr document converted from the record
* @return \ApacheSolrForTypo3\Solr\System\Solr\Document\Document The Solr document converted from the record
*/
protected function itemToDocument(Item $item, $language = 0)
protected function itemToDocument(Item $item, $language = 0): Document
{
$document = null;
$itemRecord = $this->getFullItemRecord($item, $language);
if (!is_null($itemRecord)) {
if ($itemRecord !== null) {
$itemIndexingConfiguration = $this->getItemTypeConfiguration(
$item,
$language
......@@ -77,11 +78,11 @@ class TerIndexer extends \ApacheSolrForTypo3\Solr\IndexQueue\Indexer
}
/**
* @param \Apache_Solr_Document $document
* @param \ApacheSolrForTypo3\Solr\System\Solr\Document\Document $document
* @param array $itemRecord
* @return \Apache_Solr_Document
* @return \ApacheSolrForTypo3\Solr\System\Solr\Document\Document
*/
public function addSpecialFields(\Apache_Solr_Document $document, array $itemRecord)
public function addSpecialFields(Document $document, array $itemRecord): Document
{
$extension = $this->extensionRepository->findByUid($itemRecord['uid']);
......@@ -108,24 +109,34 @@ class TerIndexer extends \ApacheSolrForTypo3\Solr\IndexQueue\Indexer
}
// does this extension supports different versions?
// @todo: use JSON with all versions to get them
$document->setField('supports7_boolS', false);
$document->setField('supports8_boolS', false);
$document->setField('supports9_boolS', false);
$typo3Support = [];
if (VersionUtility::doesExtensionSupportTypo3Version($extension, 7006000)) {
$typo3Support[] = '7 LTS';
$document->setField('supports7_boolS', true);
$supportMaintainedVersions = [];
$supportDevVersion = '';
$supportOlderVersions = [];
$ltsVersionService = GeneralUtility::makeInstance(\T3o\TerFe2\Service\LTSVersionService::class);
foreach ($ltsVersionService->getCurrentStableVersions(true) as $versionNumber) {
if (VersionUtility::doesExtensionSupportTypo3Version($extension, $versionNumber)) {
$supportMaintainedVersions[] = $ltsVersionService->getVersionLabelOfRelease($versionNumber) . ' LTS';
}
}
if (VersionUtility::doesExtensionSupportTypo3Version($extension, 8007000)) {
$typo3Support[] = '8 LTS';
$document->setField('supports8_boolS', true);
if ($ltsVersionService->getLatestDevelopmentVersion() !== $ltsVersionService->getLatestLTS() && VersionUtility::doesExtensionSupportTypo3Version($extension, $ltsVersionService->getLatestDevelopmentVersion(true))) {
$supportDevVersion = $ltsVersionService->getLatestDevelopmentVersion() . '-dev';
}
if (VersionUtility::doesExtensionSupportTypo3Version($extension, 9005000)) {
$typo3Support[] = '9 LTS';
$document->setField('supports9_boolS', true);
foreach ($ltsVersionService->getOldLTSVersions() as $versionNumber) {
if (VersionUtility::doesExtensionSupportTypo3Version($extension, $versionNumber)) {
$supportOlderVersions[] = $ltsVersionService->getVersionLabelOfRelease($versionNumber) . ' LTS';
}
}
$document->setField('typo3support_stringM', $supportMaintainedVersions);
$facetVersions = $supportMaintainedVersions;
if ($supportDevVersion) {
$facetVersions = array_merge($supportMaintainedVersions, [$supportDevVersion]);
}
$document->setField('typo3support_stringM', $typo3Support);
$document->setField('typo3supportfacets_stringM', $facetVersions);
$document->setField('typo3supportdev_stringS', $supportDevVersion);
$document->setField('typo3supportold_stringM', $supportOlderVersions);
$extensionIcon = $this->getExtensionIcon($itemRecord['ext_key'], $extension->getLastVersion()->getVersionString());
$document->setField('extensionIcon_stringS', $extensionIcon);
......
......@@ -49,7 +49,7 @@ class VersionUtility
public static function doesExtensionSupportTypo3Version(\T3o\TerFe2\Domain\Model\Extension $extension, int $mainVersion): bool
{
foreach ($extension->getVersions() as $version) {
if ($version->hasTypo3Dependency() === false || $version->isLive() === false) {
if ($version->getTypo3Dependency() === null || $version->getReviewState() === \T3o\TerFe2\Domain\Model\Version::VERSION_IS_INSECURE) {
continue;
}
......
plugin {
tx_solr {
solr {
host = solr
port = 8983
path = solr/t3o/
}
index {
queue {
ter_extension = 1
ter_extension.table = tx_terfe2_domain_model_extension
ter_extension.additionalWhereClause = last_version > 0
ter_extension.indexer = T3o\TerFe2\Solr\IndexQueue\TerIndexer
ter_extension.fields {
setRegister_ignored = LOAD_REGISTER
setRegister_ignored {
extensionVersion.cObject = SOLR_RELATION
extensionVersion.cObject {
localField = last_version
foreignLabelField = version_string
}
extensionKey.cObject = TEXT
extensionKey.cObject.field = ext_key
extensionState.cObject = SOLR_RELATION
extensionState.cObject {
localField = last_version
foreignLabelField = state
}
}
author = SOLR_CONTENT
author {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = author
}
}
title = SOLR_CONTENT
title {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = title
}
}
sortTitle_stringS = SOLR_CONTENT
sortTitle_stringS {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = title
}
}
content = SOLR_CONTENT
content {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = description
}
}
url = TEXT
url {
typolink.parameter = {$plugin.tx_solr.ter_detailpage}
typolink.additionalParams = &tx_terfe2_pi1[controller]=Extension&tx_terfe2_pi1[action]=show&tx_terfe2_pi1[extension]={field:uid}
typolink.additionalParams.insertData = 1
typolink.useCacheHash = 1
typolink.returnLast = url
}
extensionKey_textS = ext_key
extensionKey_stringS = ext_key
extensionVersion_stringS = TEXT
extensionVersion_stringS {
value = {register:extensionVersion}
insertData = 1
}
extensionState_stringS = TEXT
extensionState_stringS {
value = n/a
override {
data = register:extensionState
if {
isInList.data = register:extensionState
value = alpha,beta,stable,test,experimental,obsolete
}
}
}
extensionLastUpload_intS = SOLR_RELATION
extensionLastUpload_intS {
localField = last_version
foreignLabelField = upload_date
}
extensionLastUpload_tDateS = TEXT
extensionLastUpload_tDateS {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = upload_date
}
date = Y-m-d\TH:i:s\Z
}
extensionDownloads_intS = downloads
extensionDownloadZipUrl_stringS = TEXT
extensionDownloadZipUrl_stringS {
typolink.parameter = {$plugin.tx_solr.ter_detailpage}
typolink.additionalParams = &tx_terfe2_pi1[controller]=Extension&tx_terfe2_pi1[action]=download&tx_terfe2_pi1[extension]={field:uid}&tx_terfe2_pi1[versionString]={register:extensionVersion}&tx_terfe2_pi1[format]=zip
typolink.additionalParams.insertData = 1
typolink.useCacheHash = 1
typolink.returnLast = url
}
keywords = SOLR_RELATION
keywords {
localField = tags
multiValue = 1
}
keywords_stringM = SOLR_RELATION
keywords_stringM {
localField = tags
multiValue = 1
}
}
}
}
search {
query {
// qf parameter http://wiki.apache.org/solr/DisMaxQParserPlugin#qf_.28Query_Fields.29
queryFields = extensionKey_stringS^200.0, extensionKey_textS^1.0, keywords^55.0, title^50.0, content^20.0, author_textWstM^1.0
boostQuery = outdated_boolS:"0"^500
sortBy = extensionLastUpload_tDateS desc
}
}
}
}
[globalVar = GP:tx_solr|q =]
[else]
plugin.tx_solr.search.query.sortBy =
[global]
plugin {
tx_solr {
solr {
host = solr
port = 8983
path = solr/t3o/
}
index {
queue {
ter_extension = 1
ter_extension.table = tx_terfe2_domain_model_extension
ter_extension.additionalWhereClause = last_version > 0
ter_extension.indexer = T3o\TerFe2\Solr\IndexQueue\TerIndexer
ter_extension.fields {
setRegister_ignored = LOAD_REGISTER
setRegister_ignored {
extensionVersion.cObject = SOLR_RELATION
extensionVersion.cObject {
localField = last_version
foreignLabelField = version_string
}
extensionKey.cObject = TEXT
extensionKey.cObject.field = ext_key
extensionState.cObject = SOLR_RELATION
extensionState.cObject {
localField = last_version
foreignLabelField = state
}
}
author = SOLR_CONTENT
author {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = author
}
}
title = SOLR_CONTENT
title {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = title
}
}
sortTitle_stringS = SOLR_CONTENT
sortTitle_stringS {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = title
}
}
content = SOLR_CONTENT
content {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = description
}
}
url = TEXT
url {
typolink.parameter = {$plugin.tx_solr.ter_detailpage}
typolink.additionalParams = &tx_terfe2_pi1[controller]=Extension&tx_terfe2_pi1[action]=show&tx_terfe2_pi1[extension]={field:uid}
typolink.additionalParams.insertData = 1
typolink.useCacheHash = 1
typolink.returnLast = url
}
extensionKey_textS = ext_key
extensionKey_stringS = ext_key
extensionVersion_stringS = TEXT
extensionVersion_stringS {
value = {register:extensionVersion}
insertData = 1
}
extensionState_stringS = TEXT
extensionState_stringS {
value = n/a
override {
data = register:extensionState
if {
isInList.data = register:extensionState
value = alpha,beta,stable,test,experimental,obsolete
}
}
}
extensionLastUpload_intS = SOLR_RELATION
extensionLastUpload_intS {
localField = last_version
foreignLabelField = upload_date
}
extensionLastUpload_tDateS = TEXT
extensionLastUpload_tDateS {
cObject = SOLR_RELATION
cObject {
localField = last_version
foreignLabelField = upload_date
}
date = Y-m-d\TH:i:s\Z
}
extensionDownloads_intS = downloads
extensionDownloadZipUrl_stringS = TEXT
extensionDownloadZipUrl_stringS {
typolink.parameter = {$plugin.tx_solr.ter_detailpage}
typolink.additionalParams = &tx_terfe2_pi1[controller]=Extension&tx_terfe2_pi1[action]=download&tx_terfe2_pi1[extension]={field:uid}&tx_terfe2_pi1[versionString]={register:extensionVersion}&tx_terfe2_pi1[format]=zip
typolink.additionalParams.insertData = 1
typolink.useCacheHash = 1
typolink.returnLast = url
}
keywords = SOLR_RELATION
keywords {
localField = tags
multiValue = 1
}
keywords_stringM = SOLR_RELATION
keywords_stringM {
localField = tags
multiValue = 1
}
}
}
}
search {
query {
// qf parameter http://wiki.apache.org/solr/DisMaxQParserPlugin#qf_.28Query_Fields.29
queryFields = extensionKey_stringS^200.0, extensionKey_textS^1.0, keywords^55.0, title^50.0, content^20.0, author_textWstM^1.0
boostQuery = outdated_boolS:"0"^500
sortBy = extensionLastUpload_tDateS desc
}
}
}
}
[globalVar = GP:tx_solr|q =]
[else]
plugin.tx_solr.search.query.sortBy =
[global]
......@@ -2,6 +2,6 @@
# JSON output configuration ot the extension "ter_fe2"
# ======================================================================
plugin.tx_terfe2.jsonOutput {
# cat=TER Frontend - JSON/json/100; type=int+; label=Type number of the JSON page object
typeNum = 95832
}
\ No newline at end of file
# cat=TER Frontend - JSON/json/100; type=int+; label=Type number of the JSON page object
typeNum = 95832
}
......@@ -2,19 +2,19 @@
# JSON output configuration ot the extension "ter_fe2"
# ======================================================================
plugin.tx_terfe2.settings.jsonOutput {
typeNum = {$plugin.tx_terfe2.jsonOutput.typeNum}
typeNum = {$plugin.tx_terfe2.jsonOutput.typeNum}
}
jsonOutput = PAGE
jsonOutput {
typeNum = {$plugin.tx_terfe2.jsonOutput.typeNum}
typeNum = {$plugin.tx_terfe2.jsonOutput.typeNum}
10 =< tt_content.list.20.terfe2_pi1
10 =< tt_content.list.20.terfe2_pi1
config {
disableAllHeaderCode = 1
additionalHeaders = Content-type:application/json
xhtml_cleaning = 0
admPanel = 0
}
}
\ No newline at end of file
config {
disableAllHeaderCode = 1
additionalHeaders = Content-type:application/json
xhtml_cleaning = 0
admPanel = 0
}
}
......@@ -2,36 +2,36 @@
# RSS output configuration ot the extension "ter_fe2"
# ======================================================================
plugin.tx_terfe2.rssOutput {
# cat=TER Frontend - RSS/rss/100; type=int+; label=Type number of the RSS page object
typeNum = 837
# cat=TER Frontend - RSS/rss/100; type=int+; label=Type number of the RSS page object
typeNum = 837
# cat=TER Frontend - RSS/rss/110; type=string; label=Title of the RSS feed
title = TYPO3 - Latest 50 extensions
# cat=TER Frontend - RSS/rss/110; type=string; label=Title of the RSS feed
title = TYPO3 - Latest 50 extensions
# cat=TER Frontend - RSS/rss/120; type=string; label=Link to website
link = http://extensions.typo3.org/
# cat=TER Frontend - RSS/rss/120; type=string; label=Link to website
link = http://extensions.typo3.org/
# cat=TER Frontend - RSS/rss/130; type=string; label=Description
description = latest 50 extensions on extensions.typo3.org
# cat=TER Frontend - RSS/rss/130; type=string; label=Description
description = latest 50 extensions on extensions.typo3.org
# cat=TER Frontend - RSS/rss/140; type=string; label=Language
language = en
# cat=TER Frontend - RSS/rss/140; type=string; label=Language
language = en
# cat=TER Frontend - RSS/rss/150; type=string; label=Small image
image =
# cat=TER Frontend - RSS/rss/150; type=string; label=Small image
image =
# cat=TER Frontend - RSS/rss/160; type=int+; label=Image width
imageWidth =
# cat=TER Frontend - RSS/rss/160; type=int+; label=Image width
imageWidth =
# cat=TER Frontend - RSS/rss/170; type=int+; label=Image height
imageHeight =
# cat=TER Frontend - RSS/rss/170; type=int+; label=Image height
imageHeight =
# cat=TER Frontend - RSS/rss/180; type=string; label=RSS documentation
docs = http://blogs.law.harvard.edu/tech/rss
# cat=TER Frontend - RSS/rss/180; type=string; label=RSS documentation
docs = http://blogs.law.harvard.edu/tech/rss
# cat=TER Frontend - RSS/rss/190; type=string; label=Webmaster email address
webmaster =
# cat=TER Frontend - RSS/rss/190; type=string; label=Webmaster email address
webmaster =
# cat=TER Frontend - RSS/rss/200; type=string; label=Date format
dateFormat = D, j M Y H:i:s O
# cat=TER Frontend - RSS/rss/200; type=string; label=Date format
dateFormat = D, j M Y H:i:s O
}
......@@ -2,53 +2,53 @@
# RSS output configuration ot the extension "ter_fe2"
# ======================================================================
plugin.tx_terfe2.settings.rss.channel {
typeNum = {$plugin.tx_terfe2.rssOutput.typeNum}
title = {$plugin.tx_terfe2.rssOutput.title}
link = {$plugin.tx_terfe2.rssOutput.link}
description = {$plugin.tx_terfe2.rssOutput.description}
language = {$plugin.tx_terfe2.rssOutput.language}
image = {$plugin.tx_terfe2.rssOutput.image}
imageWidth = {$plugin.tx_terfe2.rssOutput.imageWidth}
imageHeight = {$plugin.tx_terfe2.rssOutput.imageHeight}
docs = {$plugin.tx_terfe2.rssOutput.docs}
webmaster = {$plugin.tx_terfe2.rssOutput.webmaster}
dateFormat = {$plugin.tx_terfe2.rssOutput.dateFormat}
typeNum = {$plugin.tx_terfe2.rssOutput.typeNum}
title = {$plugin.tx_terfe2.rssOutput.title}
link = {$plugin.tx_terfe2.rssOutput.link}
description = {$plugin.tx_terfe2.rssOutput.description}
language = {$plugin.tx_terfe2.rssOutput.language}
image = {$plugin.tx_terfe2.rssOutput.image}
imageWidth = {$plugin.tx_terfe2.rssOutput.imageWidth}
imageHeight = {$plugin.tx_terfe2.rssOutput.imageHeight}
docs = {$plugin.tx_terfe2.rssOutput.docs}
webmaster = {$plugin.tx_terfe2.rssOutput.webmaster}
dateFormat = {$plugin.tx_terfe2.rssOutput.dateFormat}
}
[globalVar = TSFE:type = {$plugin.tx_terfe2.rssOutput.typeNum}]
config {
disableAllHeaderCode = 1
xhtml_cleaning = none
admPanel = 0
debug = 0
disablePrefixComment = 1
metaCharset = utf-8
additionalHeaders.10.header = Content-Type:application/rss+xml;charset=utf-8
absRefPrefix = {$plugin.tx_terfe2.rssOutput.link}
}
config {
disableAllHeaderCode = 1
xhtml_cleaning = none
admPanel = 0
debug = 0
disablePrefixComment = 1
metaCharset = utf-8
additionalHeaders.10.header = Content-Type:application/rss+xml;charset=utf-8
absRefPrefix = {$plugin.tx_terfe2.rssOutput.link}
}
terRss = PAGE
terRss {
typeNum = {$plugin.tx_terfe2.rssOutput.typeNum}
10 = USER
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
vendorName = T3o
extensionName = TerFe2
pluginName = Pi1
controller = Extension
switchableControllerActions {
Extension {
1 = listLatest
}
}
terRss = PAGE
terRss {
typeNum = {$plugin.tx_terfe2.rssOutput.typeNum}
10 = USER
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
vendorName = T3o
extensionName = TerFe2
pluginName = Pi1
controller = Extension
switchableControllerActions {
Extension {
1 = listLatest
}
}
settings < plugin.tx_terfe2.settings
settings {
limit = 50
detailPid = {$plugin.tx_terfe2.settings.pages.extensionDetailPID}
startingpoint = {$plugin.tx_terfe2.persistence.storagePid}
}
}
settings < plugin.tx_terfe2.settings
settings {
limit = 50
detailPid = {$plugin.tx_terfe2.settings.pages.extensionDetailPID}
startingpoint = {$plugin.tx_terfe2.persistence.storagePid}
}
}
}
[global]
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:if condition="{version.matrixOfSupportedTypo3Versions}">
<ul class="list-inline">
<f:for each="{version.matrixOfSupportedTypo3Versions}" key="label" as="supported">
<f:if condition="{supported}">
<li class="list-inline-item badge badge-success">{label}</li>
</f:if>
<f:if condition="{version.typo3Dependency}">
<h4>This version supports TYPO3</h4>
<p>
<f:for each="{version.matrixOfSupportedTypo3Versions}" as="version">
<button class="btn btn-{version.badgeClass} btn-sm mr-2" disabled>{version.label}</button>
</f:for>
</ul>
</p>
</f:if>
</html>
......@@ -52,7 +52,7 @@
<h4 class="alert-header">
<span class="ter-ext-state-beta"><i class="fa fa-exclamation-triangle"></i></span>
Abandoned extension<br>
<small class="text-muted">This extension has no maintainer at the moment. If you like to get the maintainer of this extension, fill out our <f:link.page pageUid="{settings.pages.abandonedExtensionFormPid}">registration form</f:link.page>.</small>
<small class="text-muted">This extension has no maintainer at the moment. If you like to become the maintainer of this extension, fill out our <f:link.page pageUid="{settings.pages.abandonedExtensionFormPid}">registration form</f:link.page>.</small>
</h4>
</div>
</f:if>
......@@ -90,17 +90,15 @@
<div class="row mb-3">
<div class="col-md-8">
<p itemprop="description">{extension.lastVersion.description}</p>
<h3>
<f:render partial="VersionSupportForTypo3" arguments="{version: extension.lastVersion}" />
</h3>
<f:render partial="VersionSupportForTypo3" arguments="{version: extension.lastVersion}" />
<f:if condition="{extension.composerName}">
<p class="mb-3">
<h3>Composer support</h3>
<h4>Composer support</h4>
<f:render partial="ComposerNameWithClipboard" arguments="{composerName: extension.composerName}" />
</p>
</f:if>
<f:if condition="{extension.tags}">
<h3>Tags</h3>
<h4>Tags</h4>
<p class="tags">
<f:for each="{extension.tags}" as="tag">
<f:link.page class="btn btn-outline-info mb-1" pageUid="{settings.pages.searchResultsPid}" additionalParams="{tx_solr: {filter: {0: 'tags:{tag.title}'}}}">
......@@ -116,16 +114,16 @@
</f:for>
</div>
</f:if>
<h3>
<h4>
<f:translate key="last_upload_comment" />
</h3>
</h4>
<p itemprop="releaseNotes">
<f:format.nl2br>{extension.lastVersion.uploadComment}</f:format.nl2br>
</p>
<f:if condition="{versionHistory->f:count()} >= 1}">
<h3>
<h4>
<f:translate key="downloads_by_version" />
</h3>
</h4>
<script type="text/javascript">
var versionChartData = {extension.downloadsByVersionsAsJson -> f:format.raw()};
</script>
......
......@@ -40,7 +40,15 @@ class LTSVersionServiceTest extends UnitTestCase
*/
public function getCurrentStableVersions()
{
$this->assertSame([7, 8], $this->subject->getCurrentStableVersions());
self::assertSame([8, 9], $this->subject->getCurrentStableVersions());
}
/**
* @test
*/
public function getCurrentStableVersionsAsFullVersionNumber()
{
self::assertSame([8007009, 9005005], $this->subject->getCurrentStableVersions(true));
}
/**
......@@ -48,7 +56,15 @@ class LTSVersionServiceTest extends UnitTestCase
*/
public function getAllMaintainedVersions()
{
$this->assertSame([7, 8, '9.0'], $this->subject->getAllMaintainedVersions());
self::assertSame([8, 9, 10], $this->subject->getAllMaintainedVersions());
}
/**
* @test
*/
public function getAllMaintainedVersionsAsFullVersionNumber()
{
self::assertSame([8007009, 9005005, 10000000], $this->subject->getAllMaintainedVersions(true));
}
/**
......@@ -56,7 +72,7 @@ class LTSVersionServiceTest extends UnitTestCase
*/
public function getLatestVersionOfRelease()
{
$this->assertSame('7.6.21', $this->subject->getLatestVersionOfRelease(7));
self::assertSame('7.6.21', $this->subject->getLatestVersionOfRelease(7));
}
/**
......@@ -64,7 +80,69 @@ class LTSVersionServiceTest extends UnitTestCase
*/
public function getLatestDevelopmentVersion()
{
$this->assertSame('9.0', $this->subject->getLatestDevelopmentVersion());
self::assertSame(10, $this->subject->getLatestDevelopmentVersion());
}
/**
* @test
*/
public function getLatestDevelopmentVersionAsFullVersionNumber()
{
self::assertSame(10000000, $this->subject->getLatestDevelopmentVersion(true));
}
/**
* @test
*/
public function getAllLTSVersionsAsFullVersionNumber()
{
self::assertSame(
[
4005000,
6002000,
7006000,
8007000,
9005000
],
$this->subject->getAllLTSVersions()
);
}
/**
* @test
*/
public function getOldLTSVersionsAsFullVersionNumber()
{
self::assertSame(
[
4005000,
6002000,
7006000
],
$this->subject->getOldLTSVersions()
);
}
/**
* @test
*/
public function getVersionLabelOfNewVersion()
{
self::assertSame(
'8',
$this->subject->getVersionLabelOfRelease(8007004)
);
}
/**
* @test
*/
public function getVersionLabelOfLegacyVersion()
{
self::assertSame(
'4.5',
$this->subject->getVersionLabelOfRelease(4005031)
);
}
/**
......@@ -75,7 +153,8 @@ class LTSVersionServiceTest extends UnitTestCase
private function getSampleData()
{
$versions = [
'7' => [
7 => [
'latest' => '7.6.25',
'releases' => [
'7.6.21' => [
'version' => '7.6.21'
......@@ -88,10 +167,44 @@ class LTSVersionServiceTest extends UnitTestCase
],
]
],
'latest_stable' => '9.0.0',
'latest_old_stable' => '8.7.9',
'latest_lts' => '8.7.9',
'latest_old_lts' => '7.6.21'
8 => [
'latest' => '8.7.9',
'releases' => [
'8.7.9' => [
'version' => '8.7.9'
],
'8.7.8' => [
'version' => '8.7.8'
],
'8.7.7' => [
'version' => '8.7.7'
],
]
],
9 => [
'latest' => '9.5.5',
'releases' => [
'9.5.5' => [
'version' => '9.5.5'
],
'9.5.4' => [
'version' => '9.5.4'
]
]
],
10 => [
'latest' => '10.0.0'
],
'6.2' => [
'latest' => '6.2.31'
],
'4.5' => [
'latest' => '4.5.40'
],
'latest_stable' => '10.0.0',
'latest_old_stable' => '9.5.5',
'latest_lts' => '9.5.5',
'latest_old_lts' => '8.7.9'
];
return $versions;
......
config {
doctype = html5
absRefPrefix = /
language = en
locale_all = en_US
tx_realurl_enable = 1
compressCss = 1
compressJs = 1
concatenateCss = 1
concatenateJs = 1
}
\ No newline at end of file
......@@ -16,5 +16,13 @@ plugin.tx_ter_pi1.pid = 2
# wsdl Namespace for the soap server
plugin.tx_ter_pi1.wsdlNamespace = https://extensions.typo3.org/wsdl/tx_ter/
[applicationContext = Production/Stage]
plugin.tx_ter_pi1.wsdlNamespace = https://extensions-stage.typo3.org/wsdl/tx_ter/
plugin.tx_ter_pi1.wsdlNamespace = https://extensions-stage.typo3.org/wsdl/tx_ter/
[global]
plugin.tx_solr {
view {
templateRootPath = EXT:ter_layout/Resources/Private/Templates/Solr/
partialRootPath = EXT:ter_layout/Resources/Private/Partials/Solr/
layoutRootPath = EXT:ter_layout/Resources/Private/Layouts/Solr/
}
}
......@@ -4,5 +4,5 @@
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:ter/resources/static/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:ter_fe2/Configuration/TypoScript/Default/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:ter_layout/Configuration/TypoScript/Page.ts">
<INCLUDE_TYPOSCRIPT: source="DIR:EXT:ter_layout/Configuration/TypoScript/Ext/" extensions="ts">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:ter_layout/Configuration/TypoScript/Page.typoscript">
<INCLUDE_TYPOSCRIPT: source="DIR:EXT:ter_layout/Configuration/TypoScript/Ext/" extensions="typoscript">
page {
headerData {
1501157682 = TEXT
1501157682.value(
<!-- Piwik -->
<script type="text/javascript">
var _paq = _paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
_paq.push(['setVisitorCookieTimeout', '2592000']);
_paq.push(['setSessionCookieTimeout', '0']);
_paq.push(['setDoNotTrack', true]);
(function() {
var u="//piwik.typo3.org/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', '38']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<noscript><p><img src=//piwik.typo3.org/piwik.php?idsite=39&rec=1” style=“border:0;” alt=“” /></p></noscript>
<!-- End Piwik Code -->
)
}
}
page {
headerData {
1501157682 = TEXT
1501157682.value (
<!-- Piwik -->
<script type="text/javascript">
var _paq = _paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
_paq.push(['setVisitorCookieTimeout', '2592000']);
_paq.push(['setSessionCookieTimeout', '0']);
_paq.push(['setDoNotTrack', true]);
(function() {
var u="//piwik.typo3.org/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', '38']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<noscript><p><img src=“//piwik.typo3.org/piwik.php?idsite=39&rec=1” style=“border:0;” alt=“” /></p></noscript>
<!-- End Piwik Code -->
)
}
}