Commit 190497f6 authored by Stefan Busemann's avatar Stefan Busemann
Browse files

[FEATURE] Add membership statistic command

parent d467e2ed
Pipeline #13452 passed with stage
in 1 minute and 37 seconds
<?php
namespace T3o\T3oMembership\Command;
use Dropbox\Dropbox;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* 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!
*/
class ImportMembersCommand extends \Symfony\Component\Console\Command\Command
{
/**
* @var array
*/
protected $hookObjects = [];
/**
* @var array
*/
protected $memberships = [];
/**
* Configure the command by defining the name, options and arguments
*/
protected function configure(): void
{
$this->setDescription('Import members');
$this->addArgument('importFile', InputArgument::REQUIRED);
$this->addArgument('membershipStoragePid', InputArgument::REQUIRED);
$this->addArgument('dropboxToken', InputArgument::REQUIRED);
}
/**
* Executes the command
*
* @param InputInterface $input
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output): void
{
$io = new SymfonyStyle($input, $output);
$io->title($this->getDescription());
/** @var $logger \TYPO3\CMS\Core\Log\Logger */
$logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
$logger->debug('Execute');
$membershipRecords = $this->getDatabaseConnection()
->getConnectionForTable('tx_t3omembership_domain_model_membership')
->select(['uid', 'name'], 'tx_t3omembership_domain_model_membership')
->fetchAll();
foreach ($membershipRecords as $membershipRecord) {
$this->memberships[$membershipRecord['name']] = (int)$membershipRecord['uid'];
}
// does the import file exist?
$importFile = $this->getImportFile($input);
if (!GeneralUtility::isAbsPath($importFile)) {
$importFile = GeneralUtility::getFileAbsFileName($importFile);
}
if (!file_exists($importFile)) {
$logger->debug('No importfile', ['filename' => $importFile]);
$io->writeln('No importfile found');
return;
}
$this->initializeHookObjects();
$fileData = file($importFile);
array_shift($fileData);
foreach ($fileData as $key => $line) {
$line = iconv('ISO-8859-15', 'UTF-8', $line);
/** @noinspection PhpParamsInspection */
$fields = GeneralUtility::trimExplode("\t", $line);
$membershipUid = $this->getMembershipUid($fields[12]);
// Skip records with unknown membership types.
if (empty($membershipUid)) {
continue;
}
$subscriptionNo = (int)$fields[14];
$endDate = $this->getMemberEndDate($fields[15]);
// If the user has cancelled his membership "Gekündigt", we set the endtime enable field.
$endTime = !empty($fields[17]) ? $endDate : 0;
$hidden = false;
if ($endTime > 0 && $endTime < time()) {
$hidden = true;
}
$member = [
'name' => $fields[6],
'subscription_no' => $subscriptionNo,
'external_id' => (int)$fields[0],
'address' => $fields[7] !== '' ? $fields[7] : $fields[8],
'zip' => $fields[10],
'city' => $fields[11],
'country' => $fields[13],
'end_date' => $endDate,
'endtime' => $endTime,
'hidden' => (int)$hidden,
'starttime' => 0,
'membership' => $membershipUid,
'pid' => $input->getArgument('membershipStoragePid'),
'crdate' => time(),
'tstamp' => time(),
'invoice_email' => $fields[84],
'email' => $fields[79],
'url' => $fields[80],
'firstname' => $fields[82],
'lastname' => $fields[83]
];
$memberUid = $this->createOrUpdateMember($subscriptionNo, $member);
foreach ($this->hookObjects as $hookObject) {
if (method_exists($hookObject, 'postUpdateMemberData')) {
$hookObject->postUpdateMemberData($memberUid, $member);
}
}
}
$io->writeln('Finished.');
}
protected function getDatabaseConnection(): ConnectionPool
{
return GeneralUtility::makeInstance(ConnectionPool::class);
}
/**
* Gets importFile
*
* @return string
*/
public function getImportFile(InputInterface $input): string
{
$dropbox = new Dropbox($input->getArgument('dropboxToken'));
$dropbox->files->download('/Member-Lists/memberlist.txt', $input->getArgument('importFile'));
return $input->getArgument('importFile');
}
/**
* Instantiates all configured hook objects.
*/
protected function initializeHookObjects(): void
{
if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3omembership']['importMemberTaksHooks'])) {
return;
}
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3omembership']['importMemberTaksHooks'] as $classData) {
$hookObject = GeneralUtility::makeInstance($classData);
if (!is_object($hookObject)) {
throw new \UnexpectedValueException( // @TODO Namespace?
'The hook object class ' . $classData . ' could not be instantiated.');
}
$this->hookObjects[] = $hookObject;
}
}
protected function getMembershipUid(string $membershipName): ?int
{
$membershipName = trim(str_replace('Membership', '', $membershipName));
if (empty($this->memberships[$membershipName])) {
return null;
}
return $this->memberships[$membershipName];
}
/**
* Parses the value of the "Beginn" column to a UNIX timestamp.
*
* @param string $endDate
* @return int
*/
protected function getMemberEndDate(string $endDate): int
{
if (empty($endDate)) {
return 0;
}
$endDateTime = \DateTime::createFromFormat('d.m.Y', $endDate);
$endDateTime->setTime(0, 0, 0);
return $endDateTime->getTimestamp();
}
/**
* Checks if the member with the given subscription number already exists in the database.
* If he exists, his data will be updated, otherwise a new record will be inserted.
*
* @param int $subscriptionNo
* @param array $memberData
* @return int The uid of the updated / inserted member.
*/
protected function createOrUpdateMember(int $subscriptionNo, array $memberData): int
{
$queryBuilder = $this->getDatabaseConnection()->getQueryBuilderForTable('tx_t3omembership_domain_model_member');
// remove hidden restriction to find former member
$queryBuilder
->getRestrictions()
->removeByType(\TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction::class)
->removeByType(\TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction::class);
$statement = $queryBuilder->select('uid')->from('tx_t3omembership_domain_model_member')->where($queryBuilder->expr()
->eq('subscription_no', $queryBuilder->createNamedParameter($subscriptionNo, \PDO::PARAM_INT)))->execute();
$existingMember = $statement->fetch();
if (!empty($existingMember['uid'])) {
$memberUid = $existingMember['uid'];
$this->getDatabaseConnection()
->getConnectionForTable('tx_t3omembership_domain_model_member')
->update('tx_t3omembership_domain_model_member', $memberData, ['uid' => (int)$memberUid]);
} else {
$datebaseConnection = $this->getDatabaseConnection()->getConnectionForTable('tx_t3omembership_domain_model_member');
$datebaseConnection->insert('tx_t3omembership_domain_model_member', $memberData);
$memberUid = (int)$datebaseConnection->lastInsertId('tx_t3omembership_domain_model_member');
}
return (int)$memberUid;
}
}
<?php
namespace T3o\T3oMembership\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* 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!
*/
class MemberstatisticCommand extends \Symfony\Component\Console\Command\Command
{
/**
* @var array
*/
protected $memberships = [];
/**
* Configure the command by defining the name, options and arguments
*/
protected function configure(): void
{
$this->setDescription('Update membership statistic');
$this->addArgument('membershipStoragePid', InputArgument::REQUIRED);
}
/**
* Executes the command
*
* @param InputInterface $input
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output): void
{
$io = new SymfonyStyle($input, $output);
$io->title($this->getDescription());
/** @var $logger \TYPO3\CMS\Core\Log\Logger */
$logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
$logger->debug('Execute');
if ($this->createStatistic((int)$input->getArgument('membershipStoragePid'))) {
$io->writeln('Statistic is updated');
$logger->debug('updating statistics on PID: ' . $input->getArgument('membershipStoragePid'));
} else {
$io->writeln('Error on updating statistics');
}
}
protected function getDatabaseConnection(): ConnectionPool
{
return GeneralUtility::makeInstance(ConnectionPool::class);
}
protected function createOrUpdateMemberStatistic(int $membership, int $pid ): bool
{
$queryBuilder = $this->getDatabaseConnection()->getQueryBuilderForTable('tx_t3omembership_domain_model_member');
$statement = $queryBuilder->count('*')->from('tx_t3omembership_domain_model_member')->where($queryBuilder->expr()
->eq('membership', $membership))->execute();
$count = $statement->fetchColumn();
$memberData = array();
$memberData['year'] = date('Y');;
$memberData['month'] = date('m');;
$memberData['membership'] = $membership;
$memberData['count'] = $count;
$memberData['pid'] = $pid;
$queryBuilder = $this->getDatabaseConnection()->getQueryBuilderForTable('tx_t3omembership_domain_model_member_statistic');
$statement = $queryBuilder->select('uid')->from('tx_t3omembership_domain_model_member_statistic')
->where(
$queryBuilder->expr()->eq('year', $memberData['year']),
$queryBuilder->expr()->eq('month', $memberData['month']),
$queryBuilder->expr()->eq('membership', $membership)
)
->execute();
$existingData = $statement->fetch();
if (!empty($existingData['uid'])) {
$memberStatisticUid = $existingData['uid'];
if ($this->getDatabaseConnection()
->getConnectionForTable('tx_t3omembership_domain_model_member_statistic')
->update('tx_t3omembership_domain_model_member_statistic', $memberData,
['uid' => (int)$memberStatisticUid])) {
return true;
} else {
return false;
}
} else {
$datebaseConnection = $this->getDatabaseConnection()->getConnectionForTable('tx_t3omembership_domain_model_member_statistic');
if ($datebaseConnection->insert('tx_t3omembership_domain_model_member_statistic', $memberData)) {
return true;
} else {
return false;
}
}
}
protected function createStatistic(int $pid): bool
{
// get all membershiptypes
$queryBuilder = $this->getDatabaseConnection()->getQueryBuilderForTable('tx_t3omembership_domain_model_member');
$statement = $queryBuilder->select('uid')->from('tx_t3omembership_domain_model_membership')->execute();
$memberships = $statement->fetchAll();
$result = true;
foreach ($memberships as $membership) {
if ($this->createOrUpdateMemberStatistic((int)$membership['uid'], (int)$pid) === false) {
$result = false;
}
}
return $result;
}
}
<?php
return [
't3omembership:importmembers' => [
'class' => \T3o\T3oMembership\Command\ImportMembersCommand::class,
't3omembership:updateStatistic' => [
'class' => \T3o\T3oMembership\Command\MemberstatisticCommand::class,
'schedulable' => true,
],
];
\ No newline at end of file
];
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment