Commit b8023b17 authored by Thomas Löffler's avatar Thomas Löffler

Merge branch 'develop' into 'master'

Release 29-01-20

See merge request !343
parents e0078359 ff9db1b9
Pipeline #8421 passed with stages
in 5 minutes and 42 seconds
# ddev apache solr recipe file
#
# To use this in your own project: Copy this file to your project's .ddev folder,
# and create the folder path .ddev/solr/conf. Then, copy the solr configuration
# files for your project to .ddev/solr/conf. E.g., using Drupal Search API Solr,
# you would copy the solr-conf/5.x/ contents into .ddev/solr/conf. The configuration
# files must be present before running `ddev start`.
version: '3.6'
services:
solr: # This is the service name used when running ddev commands accepting the --service flag
container_name: ddev-${DDEV_SITENAME}-solr # This is the name of the container. It is recommended to follow the same name convention used in the main docker-compose.yml file.
image: solr:6.6.2
restart: on-failure
solr:
container_name: ddev-${DDEV_SITENAME}-solr
image: typo3solr/ext-solr:10.0.1
restart: "no"
ports:
- 8983 # Solr is served from this port inside the container
- 8983
labels:
# These labels ensure this service is discoverable by ddev
com.ddev.site-name: ${DDEV_SITENAME}
com.ddev.approot: $DDEV_APPROOT
com.ddev.app-url: $DDEV_URL
environment:
- VIRTUAL_HOST=$DDEV_HOSTNAME # This defines the host name the service should be accessible from. This will be sitename.ddev.local
- HTTP_EXPOSE=8983 # This defines the port the service should be accessible from at sitename.ddev.local
- VIRTUAL_HOST=$DDEV_HOSTNAME
- HTTP_EXPOSE=8983
volumes:
- "./solr:/solr-conf" # This exposes a mount to the host system `.ddev/solr-conf` directory.
- "./solr/configsets:/opt/solr/server/solr/configsets" # ext:solr configsets linking
- "./solr/mycores:/opt/solr/server/solr/mycores"
entrypoint:
- docker-entrypoint.sh
- solr-precreate
- t3o
- /solr-conf
# This links the solr service to the web service defined in the main docker-compose.yml, allowing applications running in the web service to access the solr service at sitename.ddev.local:8983
- "./solr:/opt/solr/server/solr"
web:
links:
- solr:$DDEV_HOSTNAME
......@@ -37,6 +37,7 @@ $exclude = [
'Upgrading.txt',
'README',
'*.example',
'Build'
];
set('rsync', [
'exclude' => array_merge($sharedDirectories, $sharedFiles, $exclude),
......@@ -51,7 +52,6 @@ set('rsync', [
'timeout' => 300
]);
set('rsync_src', './');
set('keep_releases', 10);
inventory('./.gitlab-ci/deployer/servers.yml');
set('php', '/opt/php/php72/bin/php');
set('bin_folder', 'vendor/bin/');
......
......@@ -6,6 +6,7 @@ master:
writable_mode: chmod
forward_agent: true
deploy_path: ~/ci
keep_releases: 2
develop:
stage: stage
hostname: stage-v9.typo3.org
......@@ -14,3 +15,4 @@ develop:
writable_mode: chmod
forward_agent: true
deploy_path: ~/ci
keep_releases: 2
This diff is collapsed.
......@@ -139,7 +139,7 @@ routes:
type: uri
source: 'https://typo3.org/?type=1533906435'
solr_enabled_read: true
solr_host_read: localhost
solr_host_read: solr
solr_path_read: /solr/
solr_port_read: 8983
solr_scheme_read: http
......
<?php
namespace T3o\T3orgLayout\Middleware;
/*
* 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 Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class Contributions implements \Psr\Http\Server\MiddlewareInterface
{
protected $notListedIds = [106];
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (!isset($request->getQueryParams()['contributions'])) {
return $handler->handle($request);
}
$response = new \GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json']);
$contributions = [];
$day = $request->getQueryParams()['d'] ?: 1;
$month = $request->getQueryParams()['m'] ?: date('m');
$year = $request->getQueryParams()['y'] ?: date('Y');
$apiToken = $request->getParsedBody()['token'];
if (!$apiToken) {
$response->getBody()->write(json_encode(['result' => 'error', 'error' => 'No required "token" provided.']));
return $response;
}
$beginDate = $year . '-' . $month . '-' . $day . 'T00:00:00';
$endDate = $year . '-' . $month . '-' . ($request->getQueryParams()['d'] ?: date('t', strtotime($day . '.' . $month . '.' . $year))) . 'T23:59:59';
$gitlabClient = new \GuzzleHttp\Client(['base_uri' => 'https://gitlab.typo3.org/api/v4/']);
$this->countContributions($gitlabClient, $contributions, $beginDate, $endDate, $apiToken, 'issues');
$this->countContributions($gitlabClient, $contributions, $beginDate, $endDate, $apiToken, 'merge_requests');
$contributions['result'] = 'success';
if ($contributions['contributors']) {
foreach ($contributions['contributors'] as $id => $contributor) {
if (!in_array($id, $this->notListedIds)) {
$contributors[$id] = $contributor['user']['name'];
}
}
uasort($contributors, [$this, 'lastNameSort']);
$contributions['contributors']['nameList'] = implode(', ', $contributors);
}
$response->getBody()->write(json_encode($contributions));
return $response;
}
private function countContributions(\GuzzleHttp\Client $gitlabClient, array &$contributions, string $beginDate, string $endDate, string $apiToken, string $type): void
{
$uri = $type . '/?scope=all&created_after=' . $beginDate . '&created_before=' . $endDate;
$request = new \GuzzleHttp\Psr7\Request('GET', $uri, ['Private-Token', $apiToken]);
$response = $gitlabClient->send($request);
$data = json_decode($response->getBody(), true);
$contributions['statistics'][$type] = count($data);
foreach ($data as $item) {
if (!isset($contributions['contributors'][$item['author']['id']])) {
$contributions['contributors'][$item['author']['id']] = [
'contributions' => [
$type => 0
],
'user' => $item['author']
];
}
$contributions['contributors'][$item['author']['id']]['contributions'][$type]++;
}
}
private function lastNameSort(string $a, string $b): int
{
$aLast = end(explode(' ', $a));
$bLast = end(explode(' ', $b));
return strcasecmp($aLast, $bLast);
}
}
<?php
namespace T3o\T3orgLayout\ViewHelpers\Solr;
/*
* 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!
*/
class RootlineViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper
{
use \TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
protected $doktypeList = '1';
/**
* Initialize arguments.
*
* @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
*/
public function initializeArguments()
{
$this->registerArgument('pidsRootline', 'string', 'String with UIDs of all pages from rootline', false);
}
public function render(): array
{
$rootline = [];
/** @var \ApacheSolrForTypo3\Solr\System\Solr\Document\Document $document */
$document = $this->templateVariableContainer->get('document');
if ($document['rootline']) {
/**
* Rootline looks like "4-1/2/4/7/255"
*/
$fullRootline = array_pop($document['rootline']);
$temporaryRootline = explode('-', $fullRootline);
$fullRootlineWithPidsOnly = array_pop($temporaryRootline);
$pidsRootline = explode('/', $fullRootlineWithPidsOnly);
$rootline = $this->getRootline($pidsRootline);
} elseif ($this->arguments['pidsRootline']) {
$rootline = $this->getRootline(explode('/', $this->arguments['pidsRootline']));
}
return $rootline;
}
public function getRootline(array $pidsRootline): array
{
$rootline = [];
$pageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class)
->get(\TYPO3\CMS\Frontend\Page\PageRepository::class);
// Get more information and check if page should appear
foreach ($pidsRootline as $pid) {
$page = $pageRepository->getPage((int)$pid);
if ((int)$page['hidden'] === 0 && \TYPO3\CMS\Core\Utility\GeneralUtility::inList($this->doktypeList, $page['doktype'])) {
$rootline[] = $page;
}
}
return $rootline;
}
}
TCEMAIN.linkHandler.tx_news {
TCEMAIN.linkHandler {
tx_news {
handler = TYPO3\CMS\Recordlist\LinkHandler\RecordLinkHandler
label = News
configuration {
table = tx_news_domain_model_news
storagePid = 179
hidePageTree = 1
table = tx_news_domain_model_news
storagePid = 179
hidePageTree = 1
}
scanAfter = page
}
}
TCEMAIN.linkHandler.sf_event_mgt {
sf_event_mgt {
handler = TYPO3\CMS\Recordlist\LinkHandler\RecordLinkHandler
label = Events
configuration {
table = tx_sfeventmgt_domain_model_event
storagePid = 180
hidePageTree = 1
table = tx_sfeventmgt_domain_model_event
storagePid = 180
hidePageTree = 1
}
scanAfter = page
}
}
TCEMAIN.preview {
tx_news_domain_model_news {
# Available with latest 8.7+ only
# see https://forge.typo3.org/issues/78336
useCacheHash = 1
previewPageId = 517
useDefaultLanguageRecord = 0
fieldToParameterMap {
uid = tx_news_pi1[news_preview]
}
additionalGetParameters.tx_news_pi1 {
controller = News
action = detail
}
}
}
TCEMAIN.preview {
tx_news_domain_model_news {
# Available with latest 8.7+ only
# see https://forge.typo3.org/issues/78336
useCacheHash = 1
previewPageId = 517
useDefaultLanguageRecord = 0
fieldToParameterMap {
uid = tx_news_pi1[news_preview]
}
additionalGetParameters {
tx_news_pi1.controller = News
tx_news_pi1.action = detail
}
}
}
tx_sfeventmgt.templateLayouts {
1 = Latest view
2 = List view, no category selector
1 = Latest view
2 = List view, no category selector
}
# Define Google Map API Key for Events > Locations module
tx_t3org_layout {
setGoogleMapApiKey = XXXXX
setGoogleMapApiKey = XXXXX
}
TCEMAIN {
# Owner be_users UID for new pages:
permissions.userid = 1
# Owner be_groups UID for new pages:
permissions.groupid = 1
permissions {
# User can do anything (default):
user = 31
# Group can do anything
# (normally "delete" is disabled)
group = 31
# Everybody can at least see the page
# (normally everybody can do nothing)
everybody = show
}
permissions {
# Owner be_users UID for new pages:
userid = 1
# Owner be_groups UID for new pages:
groupid = 1
# User can do anything (default):
user = 31
# Group can do anything
# (normally "delete" is disabled)
group = 31
# Everybody can at least see the page
# (normally everybody can do nothing)
everybody = show
}
}
# News are hidden by default, only admins and editors with the role "news_reviewer" are allowed to unhide records
......@@ -24,7 +25,7 @@ TCAdefaults {
}
TCEFORM {
tx_news_domain_model_news {
hidden.disabled = 1
tx_news_domain_model_news.hidden {
disabled = 1
}
}
<?php
return [
'frontend' => [
't3org-contributions' => [
'target' => \T3o\T3orgLayout\Middleware\Contributions::class,
'before' => [
'typo3/cms-frontend/timetracker'
]
]
]
];
<?php
// Add static TypoScript files
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile(
't3org_layout',
'Configuration/TypoScript/SecurityAdvisories/',
'News settings for security advisories'
);
# Include required static constants
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:solr/Configuration/TypoScript/Solr/constants.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:news/Configuration/TypoScript/constants.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:sf_event_mgt/Configuration/TypoScript/constants.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:t3o_membership/Configuration/TypoScript/constants.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:typo3_roadmap/Configuration/TypoScript/constants.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:certifications/Configuration/TypoScript/constants.txt">
# PID with fe_users
styles.content.loginform.pid = 178
# Page layout settings
tx_t3olayout.page.metamenuid = 7
tx_t3olayout.page.searchResultsPid = 184
tx_t3olayout.page.searchid = 184
tx_t3olayout.page.loginid = 187
# Styling settings
styles.content.textmedia.maxW = 1500
styles.content.textmedia.maxWInText = 1500
# Plugin persistence PIDs
plugin.tx_certifications.persistence.storagePid = 212
plugin.tx_t3omembership.persistence.storagePid = 227
plugin.tx_typo3roadmap.persistence.storagePid = 228
# Events settings
plugin.tx_sfeventmgt.settings.detailPid = 230
# News Settings
plugin.tx_news.settings.detailPid = 185
# Default constant for "plugin.txt_csseo"
plugin.tx_csseo.sitemap.pages.rootPid = 1
plugin.tx_csseo.social.defaultImage = fileadmin/t3o_common_storage/images/banner/6932872980_d788451b65_o.jpg
plugin.tx_csseo.structureddata.search.enable = 1
plugin.tx_csseo.structureddata.breadcrumb.enable = 0
plugin.tx_csseo.hreflang.enable = 0
plugin.tx_csseo.social.twitter.defaultImage = fileadmin/t3o_common_storage/images/banner/6932872980_d788451b65_o.jpg
plugin.tx_csseo.social.twitter.image.height = 329c
plugin.tx_csseo.social.twitter.creator = TYPO3 Association
plugin.tx_csseo.social.twitter.site = TYPO3Assoc
plugin.tx_csseo.sitemap.additional = sitemap.xml
plugin.tx_csseo.social.openGraph.image.width = 1024
plugin.tx_csseo.social.openGraph.image.height = 329c
plugin.tx_csseo.structureddata.search.pid = 184
\ No newline at end of file
# Include required static setup
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:solr/Configuration/TypoScript/Solr/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:solr/Configuration/TypoScript/Examples/IndexQueueNews/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:solr/Configuration/TypoScript/Examples/IndexQueueNewsContentElements/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:news/Configuration/TypoScript/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:rx_shariff/Configuration/TypoScript/PluginOnly/setup.ts">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:sf_event_mgt/Configuration/TypoScript/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:t3o_membership/Configuration/TypoScript/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:typo3_roadmap/Configuration/TypoScript/setup.txt">
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:certifications/Configuration/TypoScript/setup.txt">
<INCLUDE_TYPOSCRIPT: source="DIR:EXT:t3org_layout/Configuration/TypoScript/Ext/">
# Let table allow all classes
lib.parseFunc_RTE.externalBlocks.table.stdWrap.HTMLparser.tags.table.fixAttrib.class >
# Set active item in typo3 universe header
page.10.settings.platformKey = community
# check if news detail view
[globalVar = GP:tx_news_pi1|news > 0]
# remove all meta tags from cs_seo
page.headerData.654 >
# disable title tag
page.headerData.654.5 >
# remove meta description
page.headerData.654.7 >
# remove canonical
page.headerData.654.10 >
# remove robots
page.headerData.654.15 >
# remove open graph tags
page.headerData.654.30 >
# remove twitter card summary
page.headerData.654.35 >
# remove twitter card tags
page.headerData.654.40 >
config.noPageTitle = 2
temp.newsTitle = RECORDS
temp.newsTitle {
dontCheckPid = 1
tables = tx_news_domain_model_news
source.data = GP:tx_news_pi1|news
source.intval = 1
conf.tx_news_domain_model_news = TEXT
conf.tx_news_domain_model_news {
field = title
htmlSpecialChars = 1
}
wrap = <title>|</title>
}
page.headerData.1 >
page.headerData.1 < temp.newsTitle
[end]
config.pageTitleSeparator =
# check if news detail view
[request.getQueryParams()['tx_news_pi1]['news'] > 0]
page.headerData {
# remove all meta tags from cs_seo
654 >
}
config.noPageTitle = 2
temp.newsTitle = RECORDS
temp.newsTitle {
dontCheckPid = 1
tables = tx_news_domain_model_news
source {
data = GP:tx_news_pi1|news
intval = 1
}
conf.tx_news_domain_model_news = TEXT
conf.tx_news_domain_model_news {
field = title
htmlSpecialChars = 1
}
wrap = <title>|</title>
}
page.headerData.1 >
page.headerData.1 < temp.newsTitle
[end]
config.pageTitleSeparator =
plugin.tx_news {
view {
templateRootPaths >
templateRootPaths {
0 = EXT:news/Resources/Private/Templates/
1 = EXT:t3olayout/Resources/Private/Templates/News/
}
partialRootPaths >
partialRootPaths {
0 = EXT:news/Resources/Private/Partials/
1 = EXT:t3olayout/Resources/Private/Partials/
2 = EXT:t3olayout/Resources/Private/Partials/News/
3 = EXT:t3org_layout/Resources/Private/Partials/News/
}
layoutRootPaths >
layoutRootPaths {
0 = EXT:news/Resources/Private/Layouts/
1 = EXT:t3olayout/Resources/Private/Layouts/News/
}
widget.GeorgRinger\News\ViewHelpers\Widget\PaginateViewHelper.templateRootPath = EXT:t3olayout/Resources/Private/Templates/News/ViewHelpers/
}
settings {
list {
media {
image {
width = 480
height = 270c
}
dummyImage = typo3conf/ext/t3org_layout/Resources/Public/Images/News_Dummy.svg
}
paginate{
insertAbove = 0
}
}
defaultDetailPid = 185
listPid = 38
}
}
config.recordLinks.tx_news {
typolink {
parameter = 185
additionalParams.data = field:uid
additionalParams.wrap = &tx_news_pi1[news]=|&tx_news_pi1[controller]=News&tx_news_pi1[action]=detail
useCacheHash = 1
}
}
# Add link to RSS feed in head
page.headerData.100 = TEXT
page.headerData.100.value = <link rel="alternate" type="application/rss+xml" title="Official typo3.org news" href="/rss" />
# RSS feed with the latest 30 news (default)
[globalVar = TSFE:type = 100]
config {
disableAllHeaderCode = 1
xhtml_cleaning = none
admPanel = 0
debug = 0
disablePrefixComment = 1
metaCharset = utf-8
additionalHeaders.5.header = Content-Type:application/rss+xml;charset=utf-8
additionalHeaders.5.replace = 1
absRefPrefix = {$plugin.tx_news.rss.channel.link}
linkVars = L
}
pageNewsRSS = PAGE
pageNewsRSS {
typeNum = 100
10 = USER
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = News
vendorName = GeorgRinger
pluginName = Pi1
switchableControllerActions {
News {
1 = list
}
}
settings < plugin.tx_news.settings
settings {
limit = 30
detailPid = 185
startingpoint = 179
recursive = 1
format = xml
list.rss.channel {
title = Official typo3.org news
link = {$plugin.tx_news.rss.channel.link}
}
}
view < plugin.tx_news.view
view {
templateRootPaths {
2 = EXT:t3org_layout/Resources/Private/Templates/News/
}
}
}
}
[global]
# Add link to RSS Security feed in head
page.headerData.101 = TEXT
page.headerData.101.value = <link rel="alternate" type="application/rss+xml" title="Official typo3.org news" href="/rss-security" />
# RSS feed with the latest 30 news (security advisories)
[globalVar = TSFE:type = 101]
config {
disableAllHeaderCode = 1
xhtml_cleaning = none
admPanel = 0
debug = 0
disablePrefixComment = 1
metaCharset = utf-8
additionalHeaders.5.header = Content-Type:application/rss+xml;charset=utf-8
additionalHeaders.5.replace = 1
absRefPrefix = {$plugin.tx_news.rss.channel.link}
linkVars = L
}
pageSecurityRSS = PAGE
pageSecurityRSS {
typeNum = 101
10 = USER
10 {