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

Merge branch 'develop' into 'master'

Release 13-03-19

See merge request !140
parents 7d02daa4 44b7bf9d
Pipeline #6467 passed with stages
in 4 minutes
......@@ -14,8 +14,9 @@ webcache_enabled: false
provider: default
hooks:
post-start:
- exec: sudo apt-get update
- exec: sudo apt-get install php7.2-ldap -y
- 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
......
File added
......@@ -4,3 +4,4 @@ services:
web:
environment:
- TYPO3_CONTEXT=Development
- DEBIAN_FRONTEND=noninteractive
......@@ -9,7 +9,7 @@ variables:
STAGE_PORT: 22200
STAGE_HOST: "my-stage-v9.typo3.org"
PRODUCTION_PORT: 22201
PRODUCTION_HOST: "my-v9.typo3.org"
PRODUCTION_HOST: "my.typo3.org"
DUMP_USER: "mystage"
DUMP_EXCLUDE_TABLES_LIST: "be_groups,be_sessions,be_users,cf_cache_hash,cf_cache_hash_tags,cf_cache_imagesizes,cf_cache_imagesizes_tags,cf_cache_news_category,cf_cache_news_category_tags,cf_cache_pages,cf_cache_pages_tags,cf_cache_pagesection,cf_cache_pagesection_tags,cf_cache_rootline,cf_cache_rootline_tags,cf_extbase_datamapfactory_datamap,cf_extbase_datamapfactory_datamap_tags,cf_extbase_object,cf_extbase_object_tags,cf_extbase_reflection,cf_extbase_reflection_tags,cf_tx_solr,cf_tx_solr_configuration,cf_tx_solr_configuration_tags,cf_tx_solr_tags,fe_groups,fe_sessions,fe_users,old_users,sys_domain,sys_log,tx_solr_cache,tx_solr_cache_tags,tx_t3oslack_domain_model_slackuser"
PHP_EXECUTABLE: "/opt/php/php72/bin/php"
......
master:
stage: production
hostname: my-v9.typo3.org
hostname: my.typo3.org
port: 22201
user: my
writable_mode: chmod
......
<!---
Please read this!
Before opening a new issue, make sure to search for keywords in the issues
filtered by the "bug" label.
For Layout issues please use this tracker:
- https://git-t3o.typo3.org/t3o/t3olayout/issues?label_name%5B%5D=bug
and verify the issue you're about to submit isn't a duplicate.
--->
### Summary
(Summarize the bug encountered concisely)
### Steps to reproduce
(How one can reproduce the issue - this is very important)
### Example URL
(Add an Url where we can see the issue)
### What is the current *bug* behavior?
(What actually happens)
### What is the expected *correct* behavior?
(What you should see instead)
**Acceptence Criterias**
* [ ] Must be fullfilled
### Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
### Possible fixes
(If you can, link to the line of code that might be responsible for the problem)
/label ~bug
### Problem to solve
<!--- What problem do we solve? -->
### Further details
<!--- Include use cases, benefits, and/or goals (contributes to our vision?) -->
### Proposal
<!--- How are we going to solve the problem? Try to include the user journey! -->
### What does success look like, and how can we measure that?
<!--- Define both the success metrics and acceptance criteria. Note that success metrics indicate the desired business outcomes, while acceptance criteria indicate when the solution is working correctly. If there is no way to measure success, link to an issue that will implement a way to measure this -->
**Acceptence Criterias**
* [ ] Must be fullfilled
### Links / references
/label ~feature
### Describe the task
<!--- What problem do we solve? -->
### Further details
<!--- Include use cases, benefits, and/or goals (contributes to our vision?) -->
### What does success look like, and how can we measure that?
<!--- Define both the success metrics and acceptance criteria. Note that success metrics indicate the desired business outcomes, while acceptance criteria indicate when the solution is working correctly. If there is no way to measure success, link to an issue that will implement a way to measure this -->
**Acceptence Criterias**
* [ ] Must be fullfilled
### Links / references
/label ~task
# my.typo3.org documentation
my my.typo3.org is the entry point for all user profile related actions for
typo3.org frontend users.
## Local Extensions
* karma: manages community "kara" [documentation](extensions/karma/readme.md)
* t3o_ldap: Operation to write data into LDAP [documentation](extensions/t3o_ldap/ReadMe.md)
* t3o_slack: Sign up and link process to / with Slack [documentation](extensions/t3o_slack/Documentation/index.rst)
* t3omy: Project configuration (local templates, TCA additions, hooks) [documentation](extensions/t3omy/Documentation/index.rst)
## Service Documentation
Accountdata are documentated in a restricted project:
https://git-t3o.typo3.org/services/my.typo3.org/blob/master/README.md
\ No newline at end of file
This diff is collapsed.
......@@ -3,7 +3,6 @@
namespace T3o\Karma\Controller;
use T3o\Karma\Domain\Repository\FrontendUserRepository;
use T3o\Karma\Domain\Repository\KarmaSourceRepository;
use T3o\Karma\Domain\Repository\LedgerEntryRepository;
use T3o\Karma\Service\KarmaService;
......@@ -42,11 +41,6 @@ class AbstractController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
*/
protected $frontendUserRepository;
/**
* @var KarmaSourceRepository
*/
protected $karmaSourceRepository;
/**
* @var LedgerEntryRepository
*/
......@@ -69,18 +63,18 @@ class AbstractController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
}
/**
* @param KarmaSourceRepository $karmaSourceRepository
* @param LedgerEntryRepository $ledgerEntryRepository
*/
public function injectKarmaSourceRepository(KarmaSourceRepository $karmaSourceRepository)
public function injectLedgerEntryRepository(LedgerEntryRepository $ledgerEntryRepository)
{
$this->karmaSourceRepository = $karmaSourceRepository;
$this->ledgerEntryRepository = $ledgerEntryRepository;
}
/**
* @param LedgerEntryRepository $ledgerEntryRepository
* @return array The source codes for karma
*/
public function injectLedgerEntryRepository(LedgerEntryRepository $ledgerEntryRepository)
public function getKarmaSourceCodes()
{
$this->ledgerEntryRepository = $ledgerEntryRepository;
return array_keys($this->settings['sourceCodes']);
}
}
......@@ -48,9 +48,15 @@ class UserDisplayController extends AbstractController
$immutableValue = $this->karmaService->getImmutableKarmaForUser($frontendUser);
$mutableValue = $this->karmaService->getMutableKarmaForUser($frontendUser);
$sourceTotals = [];
foreach ($this->getKarmaSourceCodes() as $sourceCode) {
$sourceTotals[$sourceCode] = $this->karmaService->getImmutableKarmaSourceTotalForUser($sourceCode, $frontendUser);
}
$this->view->assign('immutableValue', $immutableValue);
$this->view->assign('mutableValue', $mutableValue);
$this->view->assign('hasKarma', ($immutableValue > 0 || $mutableValue > 0));
$this->view->assign('sourceTotals', $sourceTotals);
}
}
}
......@@ -48,6 +48,18 @@ class FrontendUser extends \TYPO3\CMS\Extbase\Domain\Model\FrontendUser
*/
protected $karmaCacheTimestamp = 0;
/**
* JSON encoded associative array containing totals for the karma source
*
* @var string
*/
protected $karmaSourceTotalCache = '';
/**
* @var array|null
*/
private $karmaSourceTotalCacheDecoded;
/**
* Get the cached immutable karma total
*
......@@ -107,4 +119,50 @@ class FrontendUser extends \TYPO3\CMS\Extbase\Domain\Model\FrontendUser
{
$this->karmaCacheTimestamp = $karmaCacheTimestamp;
}
/**
* Get the JSON string containing the karma source total cache array
*
* @return string
*/
public function getKarmaSourceTotalCache(): string
{
return $this->karmaSourceTotalCache;
}
/**
* Set the JSON string containing the karma source total cache array
*
* @param string $karmaSourceTotalCache
*/
public function setKarmaSourceTotalCache(string $karmaSourceTotalCache)
{
$this->karmaSourceTotalCache = $karmaSourceTotalCache;
}
/**
* @return array|null
*/
public function getKarmaSourceTotalCacheDecoded(): ?array
{
if ($this->karmaSourceTotalCacheDecoded === null) {
$this->karmaSourceTotalCacheDecoded = json_decode($this->getKarmaSourceTotalCache());
if (!is_array($this->karmaSourceTotalCacheDecoded)) {
$this->karmaSourceTotalCacheDecoded = [];
$this->setKarmaSourceTotalCache(json_encode($this->karmaSourceTotalCacheDecoded));
}
}
return $this->karmaSourceTotalCacheDecoded;
}
/**
* @param array|null $karmaSourceTotalCacheDecoded
*/
public function setKarmaSourceTotalCacheDecoded(array $karmaSouceTotalDecoded)
{
$this->karmaSourceTotalCacheDecoded = $karmaSouceTotalDecoded;
$this->setKarmaSourceTotalCache(json_encode($this->karmaSourceTotalCacheDecoded));
}
}
<?php
namespace T3o\Karma\Domain\Model;
/***************************************************************
* Copyright notice
*
* (c) 2018
* All rights reserved
*
* 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 3 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 KarmaSource extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* The title of the karma source
*
* @var string
*/
protected $title;
/**
* The alphanumeric code of the karma source
*
* Used for API calls etc.
*
* @var string
*/
protected $code;
/**
* Get the title of the karma source
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set the title of the karma source
*
* @param string $title
*/
public function setTitle(string $title)
{
$this->title = $title;
}
/**
* Get the karma source code
*
* Alphanumeric code for use in APIs etc.
*
* @return string
*/
public function getCode()
{
return $this->code;
}
/**
* Set the karma code
*
* Set the alphanumeric code for use in APIs etc.
*
* @param string $code
*/
public function setCode(string $code)
{
$this->code = $code;
}
}
......@@ -62,12 +62,22 @@ class LedgerEntry extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
protected $mutableValue;
/**
* The entry karma source
* The entry karma source code
*
* @var \T3o\Karma\Domain\Model\KarmaSource
* @var string
*/
protected $karmaSource;
/**
* @var string
*/
protected $issuer;
/**
* @var string
*/
protected $issuerAction;
/**
* Set to the related campaign if the entry is generated through a campaign
*
......@@ -197,7 +207,7 @@ class LedgerEntry extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
/**
* Get the entry karma source
*
* @return \T3o\Karma\Domain\Model\KarmaSource
* @return string
*/
public function getKarmaSource()
{
......@@ -207,13 +217,53 @@ class LedgerEntry extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
/**
* Set the entry karma source
*
* @param \T3o\Karma\Domain\Model\KarmaSource $karmaSource
* @param string $karmaSource
*/
public function setKarmaSource(KarmaSource $karmaSource)
public function setKarmaSource(string $karmaSource)
{
$this->karmaSource = $karmaSource;
}
/**
* Get the issuer code
*
* @return string
*/
public function getIssuer()
{
return $this->issuer;
}
/**
* Set the issuer code
*
* @param string $issuer
*/
public function setIssuer(string $issuer)
{
$this->issuer = $issuer;
}
/**
* Get the issuer action code
*
* @return string
*/
public function getIssuerAction()
{
return $this->issuerAction;
}
/**
* Set the issuer action code
*
* @param string $issuerAction
*/
public function setIssuerAction(string $issuerAction)
{
$this->issuerAction = $issuerAction;
}
/**
* Get the entry campaign that generated this entry, or null if no campaign
*
......
<?php
namespace T3o\Karma\Domain\Repository;
use T3o\Karma\Domain\Model\LedgerEntry;
use T3o\Karma\Service\KarmaService;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
/***************************************************************
* Copyright notice
*
* (c) 2018
* All rights reserved
*
* 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 3 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 KarmaSourceRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
/**
* @var KarmaService
*/
public $karmaService;
public function injectKarmaService(KarmaService $karmaService)
{
$this->karmaService = $karmaService;
}
/**
* Calculates the immutable karma total for a user
*
* @param \TYPO3\CMS\Extbase\Domain\Model\FrontendUser $frontendUser
* @return int
*/
public function calculateImmutableKarmaTotalForUser(\TYPO3\CMS\Extbase\Domain\Model\FrontendUser $frontendUser)
{
$frontendUser = $this->karmaService->ensureCorrectFrontendUserSubclass($frontendUser);
$queryBuilder = $this->getQueryBuilder();
$result = $queryBuilder
->addSelectLiteral($queryBuilder->expr()->sum('immutable_value'))
->from($this->getTableName())
->where(
$queryBuilder->expr()->eq('user', $frontendUser->getUid()),
$queryBuilder->expr()->eq('expired', 0)
)
->execute();
$sum = $result->fetchColumn(0);
return $sum;
}
/**
* Calculates the mutable karma total for a user
*
* @param \TYPO3\CMS\Extbase\Domain\Model\FrontendUser $frontendUser
*/
public function calculateMutableKarmaTotalForUser(\TYPO3\CMS\Extbase\Domain\Model\FrontendUser $frontendUser)
{
$frontendUser = $this->karmaService->ensureCorrectFrontendUserSubclass($frontendUser);
$queryBuilder = $this->getQueryBuilder();
$result = $queryBuilder
->addSelectLiteral($queryBuilder->expr()->sum('mutable_value'))
->from($this->getTableName())
->where(
$queryBuilder->expr()->eq('user', $frontendUser->getUid()),
$queryBuilder->expr()->eq('expired', 0)
)
->execute();
$sum = $result->fetchColumn(0);
return $sum;
}
/**
* Get the table name for this class
*
* @return string
* @internal
*/
protected function getTableName()
{
/** @var DataMapper $dataMapper */
$dataMapper = GeneralUtility::makeInstance(DataMapper::class);
/** @var DataMap $dataMap */
$dataMap = $dataMapper->getDataMap(LedgerEntry::class);
return $dataMap->getTableName();
}
/**
* Get a QueryBuilder object
*
* @return QueryBuilder
*/
protected function getQueryBuilder()
{
return GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->getTableName());
}
}
......@@ -94,6 +94,37 @@ class LedgerEntryRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
return $sum;
}
/**
* Calculates the immutable karma from a specific source for a specific user
*
* REGARDING MUTABLE VERSION: The mutable version of this function does not
* exist on purpose, because the mutable karma is intended to be source-independent
* so that e.g. writers and developers have the same usage right for their karma.
*
* @param string $source The Karma SourceCode
* @param \TYPO3\CMS\Extbase\Domain\Model\FrontendUser $frontendUser
* @return bool|string
*/
public function calculateImmutableKarmaSourceTotalForUser(string $source, \TYPO3\CMS\Extbase\Domain\Model\FrontendUser $frontendUser)
{
$frontendUser = $this->karmaService->ensureCorrectFrontendUserSubclass($frontendUser);
$queryBuilder = $this->getQueryBuilder();
$result = $queryBuilder
->addSelectLiteral($queryBuilder->expr()->sum('immutable_value'))
->from($this->getTableName())
->where(
$queryBuilder->expr()->eq('user', $frontendUser->getUid()),
$queryBuilder->expr()->eq('expired', 0),
$queryBuilder->expr()->eq('karma_source', $queryBuilder->quote($source))
)
->execute();
$sum = $result->fetchColumn(0);
return $sum;
}
/**
* Get the table name for this class
*
......
......@@ -2,13 +2,11 @@
namespace T3o\Karma\Service;
use T3o\Karma\Domain\Model\Campaign;
use T3o\Karma\Domain\Model\FrontendUser;
use T3o\Karma\Domain\Model\KarmaSource;
use T3o\Karma\Domain\Model\LedgerEntry;
use T3o\Karma\Domain\Repository\FrontendUserRepository;
use T3o\Karma\Domain\Repository\KarmaSourceRepository;
use T3o\Karma\Domain\Repository\LedgerEntryRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Domain\Model\FrontendUser as ExtbaseFrontendUser;
/***************************************************************
......@@ -47,9 +45,23 @@ class KarmaService implements \TYPO3\CMS\Core\SingletonInterface
protected $frontendUserRepository;
/**
* @var \T3o\Karma\Domain\Repository\KarmaSourceRepository
* @var array
*/
protected $karmaSourceRepository;
protected $settings;
/**
* UserProfileChangeKarmaIssuerUtility constructor.
*/
public function __construct()
{
$objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
/** @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManager $configurationManager */
$configurationManager = $objectManager->get(\TYPO3\CMS\Extbase\Configuration\ConfigurationManager::class);
$this->settings = $configurationManager->getConfiguration(
\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
'karma'
);
}
/**
* @param LedgerEntryRepository $ledgerEntryRepository
......@@ -67,14 +79,6 @@ class KarmaService implements \TYPO3\CMS\Core\SingletonInterface
$this->frontendUserRepository = $frontendUserRepository;
}
/**
* @param KarmaSourceRepository $karmaSourceRepository
*/
public function injectKarmaSourceRepository(KarmaSourceRepository $karmaSourceRepository)
{
$this->karmaSourceRepository = $karmaSourceRepository;
}
/**
* Get the imimmutable karma total from the user
*
......@@ -99,6 +103,7 @@ class KarmaService implements \TYPO3\CMS\Core\SingletonInterface
$frontendUser->setKarmaImmutableValueCache($immutableKarma);
$frontendUser->setKarmaMutableValueCache($mutableKarma);
$frontendUser->setKarmaCacheTimestamp(time());
$frontendUser->setKarmaSourceTotalCacheDecoded([]);
$this->frontendUserRepository->update($frontendUser);
}
......@@ -130,6 +135,7 @@ class KarmaService implements \TYPO3\CMS\Core\SingletonInterface
$frontendUser->setKarmaMutableValueCache($mutableKarma);
$frontendUser->setKarmaImmutableValueCache($immutableKarma);
$frontendUser->setKarmaCacheTimestamp(time());
$frontendUser->setKarmaSourceTotalCacheDecoded([]);
$this->frontendUserRepository->update($frontendUser);
}
......@@ -137,15 +143,48 @@ class KarmaService implements \TYPO3\CMS\Core\SingletonInterface
return $mutableKarma;
}
/**
* Get the immutable karma total for a specific karma source code from the user
*
* @param string $karmaSourceCode The source code to fetch the total for
* @param ExtbaseFrontendUser $frontendUser
* @param bool $ignoreCache Fetch value directly from ledger
* @param bool $updateCacheEntry Update the user's cache entry if we're ignoring cache. Will also update mutable cache.