From 624b895fd6462d9af6b379d54992f6dc9503e312 Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Mon, 2 Jan 2023 15:18:52 +0100 Subject: [PATCH] Fix coding standard. --- app/src/Commands/AbstractCliCommand.php | 31 ++++++++ app/src/Commands/InvoiceCommand.php | 37 ++++----- app/src/Commands/ReportCommand.php | 21 ++--- app/src/Commands/SelectReportTrait.php | 37 +++++---- app/src/Commands/TrackCommand.php | 3 +- .../Configuration/ConfigurationInterface.php | 4 +- .../Configuration/ConfigurationService.php | 6 +- .../Configuration/TranslationService.php | 2 + app/src/Utils/CsvReport/CsvReport.php | 23 +++--- .../Utils/CsvReport/CsvReportInterface.php | 4 +- app/src/Utils/CsvReport/ReportCsv.php | 30 +++++--- .../Utils/CsvReport/ReportCsvInterface.php | 12 +-- app/src/Utils/Mailer/MailerService.php | 23 +++--- .../Utils/PdfExport/PdfExportInterface.php | 21 +++-- app/src/Utils/PdfExport/PdfExportService.php | 26 ++++--- .../YoutrackInterface.php | 16 ++-- .../TimeTrackingServices/YoutrackService.php | 36 ++++----- app/tests/Kernel/ReportCommandTest.php | 52 +++++++++++-- app/tests/data/21-03.csv | 60 +++++++-------- app/tests/data/invoice-21-03.txt | 11 +++ app/tests/data/report-21-03.txt | 76 +++++++++++++++++++ app/tests/test-dependencies.php | 2 +- todo.txt | 4 +- 23 files changed, 372 insertions(+), 165 deletions(-) create mode 100644 app/src/Commands/AbstractCliCommand.php create mode 100644 app/tests/data/invoice-21-03.txt create mode 100644 app/tests/data/report-21-03.txt diff --git a/app/src/Commands/AbstractCliCommand.php b/app/src/Commands/AbstractCliCommand.php new file mode 100644 index 0000000..c158467 --- /dev/null +++ b/app/src/Commands/AbstractCliCommand.php @@ -0,0 +1,31 @@ +configuration = $configuration; + parent::__construct($name); + } +} diff --git a/app/src/Commands/InvoiceCommand.php b/app/src/Commands/InvoiceCommand.php index 286f924..43823bf 100644 --- a/app/src/Commands/InvoiceCommand.php +++ b/app/src/Commands/InvoiceCommand.php @@ -38,8 +38,8 @@ use function var_export; /** * Main file - invoice command. */ -class InvoiceCommand extends Command { - +class InvoiceCommand extends Command +{ use SelectReportTrait; protected $csv; @@ -50,8 +50,8 @@ class InvoiceCommand extends Command { protected $pdfExport; - const TYPE_WORK = 1; - const TYPE_EXPENSE = 2; + protected const TYPE_WORK = 1; + protected const TYPE_EXPENSE = 2; public function __construct( ReportCsvInterface $csv, @@ -61,18 +61,18 @@ class InvoiceCommand extends Command { MailerInterface $mailer, ?string $name = null ) { - $this->csv = $csv; - $this->config = $configuration; - $this->trackingService = $trackingService; - $this->pdfExport = $pdf_export; - $this->mailer = $mailer; + $this->csv = $csv; + $this->config = $configuration; + $this->trackingService = $trackingService; + $this->pdfExport = $pdf_export; + $this->mailer = $mailer; parent::__construct($name); } /** * Get configuration. */ - protected function configure() : void + protected function configure(): void { $this->setName('invoice'); $this->setDescription('Generate an invoice from (monthly) report'); @@ -124,6 +124,7 @@ class InvoiceCommand extends Command { 'expenses', 'e', InputOption::VALUE_OPTIONAL, + // phpcs:ignore 'List of additional expenses in format expense1=value1;expenses2=value2... or empty for interactive output.', false ); @@ -131,6 +132,7 @@ class InvoiceCommand extends Command { 'custom', 'c', InputOption::VALUE_OPTIONAL, + // phpcs:ignore 'Additional custom work untracked in format: name1=time1;name2=time2... Project to assign work items to has to be configured in app config. Leave empty for interactive output.', false ); @@ -149,7 +151,7 @@ class InvoiceCommand extends Command { ); } - protected function execute(InputInterface $input, OutputInterface $output) : int + protected function execute(InputInterface $input, OutputInterface $output): int { if ($input->getOption('test')) { $test = $this->trackingService->testYoutrackapi(); @@ -161,9 +163,7 @@ class InvoiceCommand extends Command { return Command::SUCCESS; } // Gets report parameter. - $this->getReportParameter($input, $output, 'tracking_service.youtrack.invoice.report'); - $report_id = $this->trackingService->getReportId(); - $file = $this->getReportCsvFilePath($input, $output, $report_id); + $file = $this->getReportCsvFilePath($input, $output, 'tracking_service.youtrack.invoice.report'); $report_name = $this->trackingService->getReportName(); if ($input->hasParameterOption('--expenses') || $input->hasParameterOption('-e')) { $expenses = $this->getCustomWorkOrExpenses($input->getOption('expenses'), self::TYPE_EXPENSE); @@ -202,7 +202,7 @@ class InvoiceCommand extends Command { return Command::SUCCESS; } - protected function getTable(OutputInterface $output, array $data) : Table + protected function getTable(OutputInterface $output, array $data): Table { $rows = $this->csv->generateTable($data); $table = new Table($output); @@ -230,7 +230,7 @@ class InvoiceCommand extends Command { * @deprecated * This method was almost exact copy of CsvReport::arangeDataForDefaultPdfExport */ - protected function generateTable(OutputInterface $output, array $data) : Table + protected function generateTable(OutputInterface $output, array $data): Table { $table = new Table($output); $table->setHeaders([ @@ -282,7 +282,7 @@ class InvoiceCommand extends Command { /** * Dummy output for testing. */ - protected function dummyOutput(InputInterface $input, OutputInterface $output) : void + protected function dummyOutput(InputInterface $input, OutputInterface $output): void { // $txt = $this->translator->trans('From [start-date] to [end-date].', [], 'rprt', 'sl_SI'); // $output->writeln($txt); @@ -326,7 +326,8 @@ class InvoiceCommand extends Command { return $output; } - protected function getCustomWorkOrExpenses($custom, $type) { + protected function getCustomWorkOrExpenses($custom, $type) + { $output = []; if (is_string($custom)) { foreach (explode(';', $custom) as $item) { diff --git a/app/src/Commands/ReportCommand.php b/app/src/Commands/ReportCommand.php index f61d56d..c6cb386 100644 --- a/app/src/Commands/ReportCommand.php +++ b/app/src/Commands/ReportCommand.php @@ -18,8 +18,8 @@ use Symfony\Component\Console\Output\OutputInterface; use function is_array; use function is_null; -class ReportCommand extends Command { - +class ReportCommand extends Command +{ use SelectReportTrait; protected $trackingService; @@ -28,6 +28,7 @@ class ReportCommand extends Command { protected $csv; + // phpcs:ignore public function __construct(ConfigurationInterface $configuration, YoutrackInterface $tracking_service, ReportCsvInterface $csv, ?string $name = null) { $this->config = $configuration; @@ -37,7 +38,8 @@ class ReportCommand extends Command { parent::__construct($name); } - protected function configure() : void { + protected function configure(): void + { $this->setName('report'); $this->setDescription('Get a time-tracking report into command line.'); $this->addOption( @@ -63,7 +65,7 @@ class ReportCommand extends Command { ); } - protected function execute(InputInterface $input, OutputInterface $output) : int + protected function execute(InputInterface $input, OutputInterface $output): int { if ($timeRange = $input->getOption('time-range')) { // @TODO: Implement time range option: @@ -77,10 +79,8 @@ class ReportCommand extends Command { $output->writeln('This option is not supported yet.'); return Command::FAILURE; } - $this->getReportParameter($input, $output); // Currently we only support csv download. - $report_id = $this->trackingService->getReportId(); - $file = $this->getReportCsvFilePath($input, $output, $report_id); + $file = $this->getReportCsvFilePath($input, $output); $report_name = $this->trackingService->getReportName(); $output->writeln("report: {$report_name}"); $data = $this->csv->generateReportTable($file); @@ -95,7 +95,7 @@ class ReportCommand extends Command { * * @TODO: Code duplication with InvoiceCommand::getTable. */ - protected function buildTable(OutputInterface $output, array $rows) : Table + protected function buildTable(OutputInterface $output, array $rows): Table { $table = new Table($output); $table->setHeaders([ @@ -109,7 +109,10 @@ class ReportCommand extends Command { $rows[$key] = new TableSeparator(); } elseif (is_array($row) && is_null($row[0]) && is_null($row[2])) { // Check which elements in array are null. - $rows[$key] = [new TableCell($row[1], ['colspan' => 2]), new TableCell((string) $row[3], ['colspan' => 2])]; + $rows[$key] = [ + new TableCell($row[1], ['colspan' => 2]), + new TableCell((string) $row[3], ['colspan' => 2]), + ]; } } $table->setRows($rows); diff --git a/app/src/Commands/SelectReportTrait.php b/app/src/Commands/SelectReportTrait.php index bcf26bf..28414c5 100644 --- a/app/src/Commands/SelectReportTrait.php +++ b/app/src/Commands/SelectReportTrait.php @@ -9,6 +9,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; +use function array_flip; + /** * Trait to select report. * @@ -16,17 +18,22 @@ use Symfony\Component\Console\Question\ChoiceQuestion; * Command must have report input option. It is not the most elegant solution * but it helps avoiding code duplication. */ -trait SelectReportTrait { - - protected function checkContext() { - if (!isset($this->trackingService)) { - return FALSE; +trait SelectReportTrait +{ + protected function checkContext() + { + if (! isset($this->trackingService)) { + return false; } return $this instanceof Command; } - protected function getReportParameter(InputInterface $input, OutputInterface $output, $default = 'tracking_service.youtrack.report.report') { - if (!$this->checkContext()) { + protected function getReportParameter( + InputInterface $input, + OutputInterface $output, + $default = 'tracking_service.youtrack.report.report' + ) { + if (! $this->checkContext()) { return Command::FAILURE; } $reports = $this->trackingService->listReports(); @@ -38,8 +45,8 @@ trait SelectReportTrait { $helper = $this->getHelper('question'); $question = new ChoiceQuestion('Select report:', $reports); $question - ->setErrorMessage('Report %s does not exist!') - ->setAutocompleterValues($reports); + ->setErrorMessage('Report %s does not exist!') + ->setAutocompleterValues($reports); $report_id = $helper->ask($input, $output, $question); $output->writeln('Report ' . $report_id . ' selected.'); } @@ -60,8 +67,14 @@ trait SelectReportTrait { $this->trackingService->setReportName(); } - protected function getReportCsvFilePath(InputInterface $input, OutputInterface $output, ?string $report_id) : ?string { - if (!$file = $input->getOption('file')) { + protected function getReportCsvFilePath( + InputInterface $input, + OutputInterface $output, + ?string $default = 'tracking_service.youtrack.report.report' + ): ?string { + if (! $file = $input->getOption('file')) { + $this->getReportParameter($input, $output, $default); + $report_id = $this->trackingService->getReportId(); $cache_clear_status = $this->trackingService->clearReportCache($report_id); if ($output->isVerbose()) { $output->writeln("Report {$report_id} cache cleared, status: {$cache_clear_status}"); @@ -75,6 +88,4 @@ trait SelectReportTrait { } return $file; } - } - diff --git a/app/src/Commands/TrackCommand.php b/app/src/Commands/TrackCommand.php index 1443271..538030e 100644 --- a/app/src/Commands/TrackCommand.php +++ b/app/src/Commands/TrackCommand.php @@ -30,10 +30,11 @@ class TrackCommand extends Command parent::__construct($name); } - protected function configure() : void + protected function configure(): void { $this->setName('youtrack'); $this->setDescription('Track time into your youtrack service'); + // phpcs:ignore $this->addUsage('rprt-cli youtrack --issue=[issue-name] --minutes=[minutes] --date=[days-ago] --description=[text] --work-type=[work-type]'); // Options or arguments? Technically they are arguments but default value could be provided by config. // Options are more suitable. diff --git a/app/src/Utils/Configuration/ConfigurationInterface.php b/app/src/Utils/Configuration/ConfigurationInterface.php index b8ee77b..75e6793 100644 --- a/app/src/Utils/Configuration/ConfigurationInterface.php +++ b/app/src/Utils/Configuration/ConfigurationInterface.php @@ -11,7 +11,7 @@ interface ConfigurationInterface /** * Get and read the configuration from file. */ - public function getConfig() : bool; + public function getConfig(): bool; /** * Get a specific configuration for key. @@ -31,5 +31,5 @@ interface ConfigurationInterface * @param string $key * Key to check for. */ - public function exists($key) : bool; + public function exists($key): bool; } diff --git a/app/src/Utils/Configuration/ConfigurationService.php b/app/src/Utils/Configuration/ConfigurationService.php index 4543ae1..064ae23 100644 --- a/app/src/Utils/Configuration/ConfigurationService.php +++ b/app/src/Utils/Configuration/ConfigurationService.php @@ -69,7 +69,7 @@ class ConfigurationService implements ConfigurationInterface return $fullPath; } } - // @TODO This should be some kind of error! + // @TODO This should be some kind of error! var_dump('Config File Not Found!'); return false; } @@ -77,7 +77,7 @@ class ConfigurationService implements ConfigurationInterface /** * Get and read the configuration from file. */ - public function getConfig() : bool + public function getConfig(): bool { if ($this->configFilePath) { $config = Yaml::parseFile($this->configFilePath); @@ -125,7 +125,7 @@ class ConfigurationService implements ConfigurationInterface * * Value of configuration key is not equal to default. */ - public function exists($key) : bool + public function exists($key): bool { return $this->get($key) !== $this->default; } diff --git a/app/src/Utils/Configuration/TranslationService.php b/app/src/Utils/Configuration/TranslationService.php index 997048c..9618fb1 100644 --- a/app/src/Utils/Configuration/TranslationService.php +++ b/app/src/Utils/Configuration/TranslationService.php @@ -4,6 +4,8 @@ declare(strict_types=1); // src/Utils/Configuration/TranslationService.php +namespace RprtCli\Utils\Translation; + use RprtCli\Utils\Configuration\ConfigurationInterface; class TranslationService diff --git a/app/src/Utils/CsvReport/CsvReport.php b/app/src/Utils/CsvReport/CsvReport.php index c05ca58..a36be37 100644 --- a/app/src/Utils/CsvReport/CsvReport.php +++ b/app/src/Utils/CsvReport/CsvReport.php @@ -39,7 +39,7 @@ class CsvReport implements CsvReportInterface /** * {@inheritdoc} */ - public function getInvoiceData(string $filePath) : array + public function getInvoiceData(string $filePath): array { $output = []; // @TODO replace with config service. @@ -69,7 +69,7 @@ class CsvReport implements CsvReportInterface * * Project key and unit of time spent. */ - protected function parseCsvFile(array $rawData) : array + protected function parseCsvFile(array $rawData): array { $config = $this->configurationService->get('projects'); foreach ($config as $key => $project) { @@ -80,7 +80,7 @@ class CsvReport implements CsvReportInterface return []; } - public function arangeDataForDefaultPdfExport(array $data) : array + public function arangeDataForDefaultPdfExport(array $data): array { [$rows, $totalHours, $totalPrice] = [[], 0, 0]; $projectsConfig = $this->configurationService->get('projects'); @@ -111,13 +111,18 @@ class CsvReport implements CsvReportInterface } // @TODO Check rate in final result. // $rows[] = [$this->translator->trans('Sum'), $totalHours, $config['price'], $totalPrice]; - $rows[] = ['Gesamt netto', number_format($totalHours, 2, ',', '.'), number_format($config['price'], 2, ',', '.'), number_format($totalPrice, 2, ',', '.')]; + $rows[] = [ + 'Gesamt netto', + number_format($totalHours, 2, ',', '.'), + number_format($config['price'], 2, ',', '.'), + number_format($totalPrice, 2, ',', '.') + ]; $rows[] = [null, null, 'Gessamt brutto', number_format($totalPrice, 2, ',', '.')]; return $rows; } - protected function dummyConfig() : array + protected function dummyConfig(): array { return [ 'projects' => [ @@ -127,15 +132,15 @@ class CsvReport implements CsvReportInterface 'price' => 26, // optional specify columns ], - 'WV' => [ - 'name' => 'Wirtschaftsverlag', - 'pattern' => 'WV-[0-9]+', + 'TNP' => [ + 'name' => 'Triglav National Park', + 'pattern' => 'TNP-[0-9]+', 'price' => 26, // optional specify columns ], 'Other' => [ 'name' => 'Other projects', - 'pattern' => '(?!.\bLDP\b)(?!.\bWV\b)', + 'pattern' => '(?!.\bLDP\b)(?!.\bTNP\b)', 'price' => 26, // optional specify columns ], diff --git a/app/src/Utils/CsvReport/CsvReportInterface.php b/app/src/Utils/CsvReport/CsvReportInterface.php index 4db4596..91ee52e 100644 --- a/app/src/Utils/CsvReport/CsvReportInterface.php +++ b/app/src/Utils/CsvReport/CsvReportInterface.php @@ -17,7 +17,7 @@ interface CsvReportInterface * * Project key as key and number of hours as value. */ - public function getInvoiceData(string $filePath) : array; + public function getInvoiceData(string $filePath): array; /** * Data for default drunomics pdf export. @@ -25,5 +25,5 @@ interface CsvReportInterface * * Parsed data from csv report. */ - public function arangeDataForDefaultPdfExport(array $data) : array; + public function arangeDataForDefaultPdfExport(array $data): array; } diff --git a/app/src/Utils/CsvReport/ReportCsv.php b/app/src/Utils/CsvReport/ReportCsv.php index d17823a..89e9eec 100644 --- a/app/src/Utils/CsvReport/ReportCsv.php +++ b/app/src/Utils/CsvReport/ReportCsv.php @@ -46,7 +46,7 @@ class ReportCsv implements ReportCsvInterface /** * {@inheritdoc} */ - public function getInvoiceData(string $filePath) : array + public function getInvoiceData(string $filePath): array { $output = []; // @TODO replace with config service. @@ -80,7 +80,7 @@ class ReportCsv implements ReportCsvInterface * * Project key and unit of time spent. */ - protected function parseCsvFile(array $rawData) : array + protected function parseCsvFile(array $rawData): array { $config = $this->configurationService->get('projects'); foreach ($config as $key => $project) { @@ -94,7 +94,7 @@ class ReportCsv implements ReportCsvInterface /** * Input is array of Work elements and expenses. */ - public function generateTable(array $data) : array + public function generateTable(array $data): array { [$rows, $totalHours, $totalPrice, $add_separator] = [[], 0, 0, false]; $projectsConfig = $this->configurationService->get('projects'); @@ -126,8 +126,13 @@ class ReportCsv implements ReportCsvInterface } if ($add_separator) { // @TODO replace separators with constants for normal separating. - $rows[] = null; - $rows[] = ['Gesamt netto', number_format($totalHours, 2, ',', '.'), ' ', number_format($totalPrice, 2, ',', '.')]; + $rows[] = null; + $rows[] = [ + 'Gesamt netto', + number_format($totalHours, 2, ',', '.'), + ' ', + number_format($totalPrice, 2, ',', '.') + ]; $add_separator = false; } if (empty($data)) { @@ -168,7 +173,7 @@ class ReportCsv implements ReportCsvInterface /** * {@inheritdoc} */ - public function arangeDataForDefaultPdfExport(array $data) : array + public function arangeDataForDefaultPdfExport(array $data): array { $rows = $this->generateTable($data); $header = $this->configurationService->get('export.labels', null); @@ -189,9 +194,15 @@ class ReportCsv implements ReportCsvInterface return []; } $explodeMinus = fn($ticket) => explode('-', $ticket)[0] ?? 'UNKNOWN'; - [$previous, $time_sum, $project_time, $table, $all_projects] = [$data[0]['id'], 0, 0, [], [$explodeMinus($data[0]['id'])]]; + [$previous, $time_sum, $project_time, $table, $all_projects] = [ + $data[0]['id'], + 0, + 0, + [], + [$explodeMinus($data[0]['id'])] + ]; foreach ($data as $line) { - $project = $explodeMinus($line['id']); + $project = $explodeMinus($line['id']); $previous_project = $explodeMinus($previous); if ($project !== $previous_project) { // When project changes, add a sum of time for that project. @@ -220,7 +231,7 @@ class ReportCsv implements ReportCsvInterface /** * {@inheritdoc} */ - protected function parseReportData(string $filePath) : array + protected function parseReportData(string $filePath): array { $output = []; // @TODO replace with config service. @@ -242,5 +253,4 @@ class ReportCsv implements ReportCsvInterface } return $output; } - } diff --git a/app/src/Utils/CsvReport/ReportCsvInterface.php b/app/src/Utils/CsvReport/ReportCsvInterface.php index 2557957..a758a05 100644 --- a/app/src/Utils/CsvReport/ReportCsvInterface.php +++ b/app/src/Utils/CsvReport/ReportCsvInterface.php @@ -12,17 +12,17 @@ interface ReportCsvInterface /** * Normal separator. */ - const SEPARATOR_SOFT = false; + public const SEPARATOR_SOFT = false; /** * Medium separator. Next line bold. */ - const SEPARATOR_MEDIUM = null; + public const SEPARATOR_MEDIUM = null; /** * Next line should be bold and centered. */ - const SEPARATOR_HARD = 0; + public const SEPARATOR_HARD = 0; /** * Returns array of hours per configured projects. @@ -32,14 +32,14 @@ interface ReportCsvInterface * * Project key as key and number of hours as value. */ - public function getInvoiceData(string $filePath) : array; + public function getInvoiceData(string $filePath): array; /** * Returns array of rows created from array of InvoiceElements. * * If row is null, it is meant to be a table separator. */ - public function generateTable(array $data) : array; + public function generateTable(array $data): array; /** * Data for default drunomics pdf export. @@ -47,5 +47,5 @@ interface ReportCsvInterface * * Parsed data from csv report. */ - public function arangeDataForDefaultPdfExport(array $data) : array; + public function arangeDataForDefaultPdfExport(array $data): array; } diff --git a/app/src/Utils/Mailer/MailerService.php b/app/src/Utils/Mailer/MailerService.php index 72b3380..eee2f23 100644 --- a/app/src/Utils/Mailer/MailerService.php +++ b/app/src/Utils/Mailer/MailerService.php @@ -52,17 +52,17 @@ class MailerService implements MailerInterface $this->pdf = $pdf; } - public function setRecipients(array $to) : void + public function setRecipients(array $to): void { $this->to = $to; } - public function setSubject(string $subject) : void + public function setSubject(string $subject): void { $this->subject = $subject; } - public function setAttachment(string $path) : void + public function setAttachment(string $path): void { // @TODO - add some error handling. $this->attachment = $path; @@ -115,7 +115,7 @@ class MailerService implements MailerInterface return $this->password; } - public function sendMail(string $from, array $to, string $subject, string $text, array $attachment = []) : void + public function sendMail(string $from, array $to, string $subject, string $text, array $attachment = []): void { $email = new Email(); $email->from($from); @@ -153,9 +153,14 @@ class MailerService implements MailerInterface return new Mailer($transport); } - public function sendDefaultMail(string $output) : void + public function sendDefaultMail(string $output): void { - $tokens = $this->pdf->gatherTokensForTemplate($this->getEmailTemplatePath(), false, $this->getDefaultTokens(), 'email.tokens'); + $tokens = $this->pdf->gatherTokensForTemplate( + $this->getEmailTemplatePath(), + false, + $this->getDefaultTokens(), + 'email.tokens' + ); $text = $this->pdf->replaceTokensInTemplate($this->getEmailTemplatePath(), $tokens); $this->sendMail( $this->getProperty('from'), @@ -166,7 +171,7 @@ class MailerService implements MailerInterface ); } - public function getDefaultTokens() : array + public function getDefaultTokens(): array { $tokens = []; $date = strtotime('-1 month'); @@ -175,7 +180,7 @@ class MailerService implements MailerInterface return $tokens; } - protected function getEmailTemplatePath() : ?string + protected function getEmailTemplatePath(): ?string { if (! isset($this->templatePath)) { $template_path = $this->config->get('email.template_path', false); @@ -190,7 +195,7 @@ class MailerService implements MailerInterface return $this->templatePath; } - public function setEmailTemplatePath(string $path) : void + public function setEmailTemplatePath(string $path): void { if (file_exists($path)) { $this->templatePath = $path; diff --git a/app/src/Utils/PdfExport/PdfExportInterface.php b/app/src/Utils/PdfExport/PdfExportInterface.php index 04c2e86..2f1b505 100644 --- a/app/src/Utils/PdfExport/PdfExportInterface.php +++ b/app/src/Utils/PdfExport/PdfExportInterface.php @@ -13,9 +13,9 @@ interface PdfExportInterface * Retrieves path to template file either from command option, configuration * or from uer input. */ - public function getTemplatePath() : ?string; + public function getTemplatePath(): ?string; - public function setTemplatePath(string $path) : void; + public function setTemplatePath(string $path): void; /** * Creates html table from parsed csv data. @@ -23,12 +23,12 @@ interface PdfExportInterface * * First line is header. The rest of them is table body. */ - public function parsedDataToHtmlTable(array $data) : ?string; + public function parsedDataToHtmlTable(array $data): ?string; /** * Reads the template file and replaces token values. */ - public function replaceTokensInTemplate(string $template_path, array $tokens) : ?string; + public function replaceTokensInTemplate(string $template_path, array $tokens): ?string; /** * Creates and export file. @@ -38,7 +38,7 @@ interface PdfExportInterface * * True if export was successfull. */ - public function pdfExport(string $html) : bool; + public function pdfExport(string $html): bool; /** * Goes through the whole process of creating a pdf for the invoice. @@ -48,7 +48,7 @@ interface PdfExportInterface * * Path of the pdf file. */ - public function fromDefaultDataToPdf(array $nice_data, array $tokens = []) : string; + public function fromDefaultDataToPdf(array $nice_data, array $tokens = []): string; /** * Sets output file override via command paramater. @@ -56,7 +56,7 @@ interface PdfExportInterface * * Path of the output pdf file ('/tmp/test.pdf'). */ - public function setOutput(string $output) : void; + public function setOutput(string $output): void; // @TODO support multiple templates by adding template id in config. // @TODO implement twig. @@ -75,5 +75,10 @@ interface PdfExportInterface * * Token keys and values array. */ - public function gatherTokensForTemplate(string $template_path, bool $skip_missing, array $runtime_tokens = [], string $config = 'export.token') : array; + public function gatherTokensForTemplate( + string $template_path, + bool $skip_missing, + array $runtime_tokens = [], + string $config = 'export.token' + ): array; } diff --git a/app/src/Utils/PdfExport/PdfExportService.php b/app/src/Utils/PdfExport/PdfExportService.php index 0972825..32c50a0 100644 --- a/app/src/Utils/PdfExport/PdfExportService.php +++ b/app/src/Utils/PdfExport/PdfExportService.php @@ -35,7 +35,7 @@ class PdfExportService implements PdfExportInterface $this->mpdf = $mpdf; } - public function getTemplatePath() : ?string + public function getTemplatePath(): ?string { if (! isset($this->templatePath)) { $template_path = $this->config->get('export.template_path', false); @@ -50,7 +50,7 @@ class PdfExportService implements PdfExportInterface return $this->templatePath; } - public function setTemplatePath(string $path) : void + public function setTemplatePath(string $path): void { if (file_exists($path)) { $this->templatePath = $path; @@ -64,7 +64,7 @@ class PdfExportService implements PdfExportInterface // @TODO would it make sense to allow more per user extending? // @TODO - too much assumptions on data structure. Create a class with // precise data structure and use that to pass the data around. - public function parsedDataToHtmlTable(array $data) : ?string + public function parsedDataToHtmlTable(array $data): ?string { $table = ''; $header = array_shift($data); @@ -105,7 +105,7 @@ class PdfExportService implements PdfExportInterface return $table; } - public function replaceTokensInTemplate(string $template_path, array $tokens) : ?string + public function replaceTokensInTemplate(string $template_path, array $tokens): ?string { $template = file_get_contents($template_path); foreach ($tokens as $key => $value) { @@ -115,7 +115,7 @@ class PdfExportService implements PdfExportInterface } // @TODO write a method to gather tokens. - public function getTokensInTemplate(string $template) : array + public function getTokensInTemplate(string $template): array { // @TODO find substrings of type [[key]] preg_match_all('/\[\[([a-z0-9-_]+)\]\]/', $template, $match); @@ -138,8 +138,12 @@ class PdfExportService implements PdfExportInterface * * Token keys and values array. */ - public function gatherTokensForTemplate(string $template_path, bool $skip_missing = false, array $runtime_tokens = [], string $config = 'export.tokens') : array - { + public function gatherTokensForTemplate( + string $template_path, + bool $skip_missing = false, + array $runtime_tokens = [], + string $config = 'export.tokens' + ): array { [$tokens, $missing] = [[], []]; $token_keys = $this->getTokensInTemplate(file_get_contents($template_path)); $config_tokens = $this->config->get($config); @@ -157,7 +161,7 @@ class PdfExportService implements PdfExportInterface return $tokens; } - public function pdfExport(string $html, $output = null) : bool + public function pdfExport(string $html, $output = null): bool { $this->mpdf->SetProtection(['print']); // @TODO make configurable. @@ -182,12 +186,12 @@ class PdfExportService implements PdfExportInterface return $output; } - public function setOutput(string $path) : void + public function setOutput(string $path): void { $this->output = $path; } - public function fromDefaultDataToPdf(array $data, array $tokens = []) : string + public function fromDefaultDataToPdf(array $data, array $tokens = []): string { $template_path = $this->getTemplatePath(); $tokens = $this->defaultTokens(); @@ -204,7 +208,7 @@ class PdfExportService implements PdfExportInterface /** * Get default tokens. */ - protected function defaultTokens() : array + protected function defaultTokens(): array { $tokens = []; $tokens['today'] = date('j. m. y'); diff --git a/app/src/Utils/TimeTrackingServices/YoutrackInterface.php b/app/src/Utils/TimeTrackingServices/YoutrackInterface.php index 1caa15b..97bad20 100644 --- a/app/src/Utils/TimeTrackingServices/YoutrackInterface.php +++ b/app/src/Utils/TimeTrackingServices/YoutrackInterface.php @@ -9,12 +9,12 @@ interface YoutrackInterface /** * Check if client can sign into youtrack with provided token. */ - public function testYoutrackapi() : ?string; + public function testYoutrackapi(): ?string; /** * Get the id of the report from configuration. */ - public function getReportId() : ?string; + public function getReportId(): ?string; /** * Downloads report and returns file path. @@ -25,7 +25,7 @@ interface YoutrackInterface * * If fetch was unsuccssefull return false, otherwise the file path. */ - public function downloadReport(string $report_id) : ?string; + public function downloadReport(string $report_id): ?string; /** * Get a list of reports. @@ -33,9 +33,11 @@ interface YoutrackInterface * * Array of reports with ids as keys and names as values. */ - public function listReports() : array; + public function listReports(): array; - public function setReportId(string $report_id) :void; - public function setReportName(?string $report_name = NULL) :void; - public function getReportName() : ?string; + public function setReportId(string $report_id): void; + + public function setReportName(?string $report_name = null): void; + + public function getReportName(): ?string; } diff --git a/app/src/Utils/TimeTrackingServices/YoutrackService.php b/app/src/Utils/TimeTrackingServices/YoutrackService.php index c383051..d333553 100644 --- a/app/src/Utils/TimeTrackingServices/YoutrackService.php +++ b/app/src/Utils/TimeTrackingServices/YoutrackService.php @@ -36,7 +36,7 @@ class YoutrackService implements YoutrackInterface protected ClientInterface $httpClient; protected string $report_id; - protected ?string $reportName = NULL; + protected ?string $reportName = null; public function __construct(ConfigurationInterface $config, ClientInterface $http_client) { @@ -44,7 +44,7 @@ class YoutrackService implements YoutrackInterface $this->httpClient = $http_client; } - public function testYoutrackapi() : ?string + public function testYoutrackapi(): ?string { // Get base url from config or add input. // Get token or add input. @@ -88,7 +88,7 @@ class YoutrackService implements YoutrackInterface ]; } - public function getReportId() : ?string + public function getReportId(): ?string { // --report option value should take precedence. // @TODO error handling. @@ -102,29 +102,30 @@ class YoutrackService implements YoutrackInterface return $yt_report_id; } - public function setReportId(string $report_id) : void + public function setReportId(string $report_id): void { $this->report_id = $report_id; } - public function setReportName(?string $report_name = NULL) : void { - if (!$report_name) { + public function setReportName(?string $report_name = null): void + { + if (! $report_name) { $reports = $this->listReports(); if ($report_id = $this->getReportId()) { - $report_name = $reports[$report_id] ?? NULL; - } - else { - $report_name = NULL; + $report_name = $reports[$report_id] ?? null; + } else { + $report_name = null; } } $this->reportName = $report_name; } - public function getReportName() : ?string { + public function getReportName(): ?string + { return $this->reportName; } - public function downloadReport(string $report_id) : ?string + public function downloadReport(string $report_id): ?string { $path = "youtrack/api/reports/$report_id/export/csv"; $query = ['$top' => -1]; @@ -160,7 +161,7 @@ class YoutrackService implements YoutrackInterface throw new Exception("Unable to download report {$report_id}!"); } - protected function getYtToken() : string + protected function getYtToken(): string { if (isset($this->ytToken)) { return $this->ytToken; @@ -172,12 +173,12 @@ class YoutrackService implements YoutrackInterface return $yt_token; } - public function setYtToken(string $token) : void + public function setYtToken(string $token): void { $this->ytToken = $token; } - protected function getYtUrl(string $path = '') : ?string + protected function getYtUrl(string $path = ''): ?string { if (isset($this->ytBaseUrl)) { $yt_base_url = $this->ytBaseUrl; @@ -198,7 +199,7 @@ class YoutrackService implements YoutrackInterface $this->ytBaseUrl = $base_url; } - public function listReports() : array + public function listReports(): array { // Now filter results by own = true; $url = '/youtrack/api/reports'; @@ -217,11 +218,12 @@ class YoutrackService implements YoutrackInterface return $reports; } - public function clearReportCache(string $report_id) : int + public function clearReportCache(string $report_id): int { $path = "/youtrack/api/reports/${report_id}/status"; $query = [ '$top' => -1, + // phpcs:ignore 'fields' => 'calculationInProgress,error(id),errorMessage,isOutdated,lastCalculated,progress,wikifiedErrorMessage', ]; $post = [ diff --git a/app/tests/Kernel/ReportCommandTest.php b/app/tests/Kernel/ReportCommandTest.php index cb34dea..032280c 100644 --- a/app/tests/Kernel/ReportCommandTest.php +++ b/app/tests/Kernel/ReportCommandTest.php @@ -11,8 +11,22 @@ use DI\ContainerBuilder; use RprtCli\Commands\InvoiceCommand; use RprtCli\Commands\ReportCommand; +/** + * Report and invoice command test. + * + * Does not cover the part of talking to the api, nor does it yet cover email + * and pdf generation. @TODO + */ class ReportCommandTest extends TestCase { + protected const INPUT_CSV_FILE = __DIR__ . '/../data/21-03.csv'; + + protected const REPORT_OUTPUT_FILE = __DIR__ . '/../data/report-21-03.txt'; + + protected const INVOICE_OUTPUT_FILE = __DIR__ . '/../data/invoice-21-03.txt'; + + protected const INVOICE_OUTPUT_PDF = __DIR__ . '/../data/output/Invoice-test.pdf'; + public function testExecute() { $builder = new ContainerBuilder(); $builder->addDefinitions(__DIR__ . '/../test-dependencies.php'); @@ -26,9 +40,9 @@ class ReportCommandTest extends TestCase { $application->add($reportCommand); - $command = $application->find('report'); - $commandTester = new CommandTester($command); - $commandTester->execute([ + $reportCommand = $application->find('report'); + $reportCommandTester = new CommandTester($reportCommand); + $reportCommandTester->execute([ // pass arguments to the helper '--file' => __DIR__ . '/../data/21-03.csv', @@ -38,13 +52,37 @@ class ReportCommandTest extends TestCase { // e.g: '--some-option' => ['option_value'], ]); - $commandTester->assertCommandIsSuccessful(); + $reportCommandTester->assertCommandIsSuccessful(); // the output of the command in the console - $output = $commandTester->getDisplay(); - var_dump($output); + $output = $reportCommandTester->getDisplay(); + // var_dump($output); $this->assertStringContainsString('21-03.csv', $output); + $this->assertStringEqualsFile(self::REPORT_OUTPUT_FILE, $output); + + $invoiceCommand = $application->find('invoice'); + $invoiceCommandTester = new CommandTester($invoiceCommand); + $invoiceCommandTester->execute([ + '--file' => self::INPUT_CSV_FILE, + '--pdf' => TRUE, + ]); + + $invoiceCommandTester->assertCommandIsSuccessful(); + + // the output of the command in the console + $invoice_output = $invoiceCommandTester->getDisplay(); + var_dump($invoice_output); + $this->assertStringContainsString('21-03.csv', $invoice_output); + $this->assertStringEqualsFile(self::INVOICE_OUTPUT_FILE, $invoice_output); + + // $invoiceCommandTester->execute([ + // '--file' => self::INPUT_CSV_FILE, + // '--pdf' + // ]); + // $invoice_output = $invoiceCommandTester->getDisplay(); + // var_dump($invoice_output); + // $this->assertFileExists(); - // ... } + } diff --git a/app/tests/data/21-03.csv b/app/tests/data/21-03.csv index 6d360bf..819ae73 100644 --- a/app/tests/data/21-03.csv +++ b/app/tests/data/21-03.csv @@ -3,13 +3,13 @@ Group name,Item,Item Summary,Estimation time,Spent time -,DEV-56,Developer training,0,60 -,DEV-122,Daily standup,0,255 -,INF-6,"Infrastructure misc, diverse",0,75 --,KUR-181,Sprint meetings (PM),240,390 --,KUR-507,(TKT-307) Change webhook integration for Slack,0,330 --,KUR-552,(TKT-740) Allow kicking users out of collections,780,45 --,KUR-554,(TKT-1448) Adaptions in Backend,0,30 --,KUR-556,[story] (TKT-1393) Make Paragraph embedding more user friendly,0,75 --,KUR-558,(TKT-1467) Full copy of article doesn't update the timestamp,0,15 --,KUR-562,(TKT-1441) Implement SEO title in BE,0,45 +-,SND-181,Sprint meetings (PM),240,390 +-,SND-507,(TKT-307) Change webhook integration for Slack,0,330 +-,SND-552,(TKT-740) Allow kicking users out of collections,780,45 +-,SND-554,(TKT-1448) Adaptions in Backend,0,30 +-,SND-556,[story] (TKT-1393) Make Paragraph embedding more user friendly,0,75 +-,SND-558,(TKT-1467) Full copy of article doesn't update the timestamp,0,15 +-,SND-562,(TKT-1441) Implement SEO title in BE,0,45 -,LDP-668,Add json-ld schema.org metadata to articles,0,300 -,LDP-685,"LDP-Contentpool sitemaps. Extend ""simple_sitemap_extended"" setup to support per front-end site sitemaps.",0,15 -,LDP-692,Output json-ld script,0,30 @@ -28,26 +28,26 @@ Group name,Item,Item Summary,Estimation time,Spent time -,LDP-740,CP: Add portal path prefixes,480,30 -,LDP-741,Defects marketing Blocks,0,450 -,LDP-742,[Red Alert] Develop branch fails to build,0,45 --,VAL-8,Plan hosting setup on custom hosting provider,0,45 --,WV-31,"Internal sprint meetings (PM, fixed-price).",0,150 --,WV-4304,"(ODT-1240) Structured data on article (satellite) pages and overview pages such as the startpage, branch, topic & channel pages.",600,750 --,WV-4305,(ODT-1202) Add mobile-banner-3 & 4 (advertisement in articles),0,60 --,WV-4326,(ODT-1174) Make image optional in the Call to Action block,135,60 --,WV-4355,(ODT-1270) Add article title to breadcrumbs,0,270 --,WV-4359,"(ODT-1254) Display the text paragraph ""zwischentitel"" in H2",0,90 --,WV-4372,(ODT-1297) Branch analytics for articles associated with specific branch (GA),135,15 --,WV-4384,(ODT-1306) Layout-builder rendering in Chrome browser,120,120 --,WV-4393,WVsat docker build error,0,90 --,WV-4410,(ODT-1317) SOLR Search optimization >> suggested articles does NOT affect the relevance for search results.,375,30 --,WV-4411,Extend simple_sitemap_extensions for dynamic variants & Install and configure simple_sitemap_extensions,600,2070 --,WV-4412,Implement custom dynamic variants for sitemaps to group by month,0,105 --,WV-4414,Invalid JSON in the cache_tools composer.json file,0,60 --,WV-4421,WV Satellites Hand bau image file entities are not replicated,0,15 --,WV-4422,"[Red Alert] Behat test fail. ""Demo content loaded..Error pages work.""",0,75 --,WV-4423,(ODT-1325) Site managers must be able to change article status from Unpublished to Unpublished,0,15 --,WV-4425,Unpublished Advertorials are returned,0,30 --,WV-4427,"(ODT-1332) ""Og: image"" is not specified explicitly",120,15 --,WV-4437,"(ODT-1339) User (id 511) on wv-contentpool is locked and cannot access the system.",0,30 --,WV-4442,(ODT-1341) Custom HTML block is not rendered,0,120 --,WV-4478,(ODT-1368) Hosting provider transition of all projects hosted on their OpenShift infrastructure to the new Kuberneets (k8) infrastructure.,0,90 --,WV-4480,(ODT-1370) Error: Call to a member function getUrl() on null / cannot save an article on stage systems,0,90 +-,TES-8,Plan hosting setup on custom hosting provider,0,45 +-,TNP-31,"Internal sprint meetings (PM, fixed-price).",0,150 +-,TNP-4304,"(ODT-1240) Structured data on article (satellite) pages and overview pages such as the startpage, branch, topic & channel pages.",600,750 +-,TNP-4305,(ODT-1202) Add mobile-banner-3 & 4 (advertisement in articles),0,60 +-,TNP-4326,(ODT-1174) Make image optional in the Call to Action block,135,60 +-,TNP-4355,(ODT-1270) Add article title to breadcrumbs,0,270 +-,TNP-4359,"(ODT-1254) Display the text paragraph ""zwischentitel"" in H2",0,90 +-,TNP-4372,(ODT-1297) Branch analytics for articles associated with specific branch (GA),135,15 +-,TNP-4384,(ODT-1306) Layout-builder rendering in Chrome browser,120,120 +-,TNP-4393,TNPsat docker build error,0,90 +-,TNP-4410,(ODT-1317) SOLR Search optimization >> suggested articles does NOT affect the relevance for search results.,375,30 +-,TNP-4411,Extend simple_sitemap_extensions for dynamic variants & Install and configure simple_sitemap_extensions,600,2070 +-,TNP-4412,Implement custom dynamic variants for sitemaps to group by month,0,105 +-,TNP-4414,Invalid JSON in the cache_tools composer.json file,0,60 +-,TNP-4421,TNP Satellites Hand bau image file entities are not replicated,0,15 +-,TNP-4422,"[Red Alert] Behat test fail. ""Demo content loaded..Error pages work.""",0,75 +-,TNP-4423,(ODT-1325) Site managers must be able to change article status from Unpublished to Unpublished,0,15 +-,TNP-4425,Unpublished Advertorials are returned,0,30 +-,TNP-4427,"(ODT-1332) ""Og: image"" is not specified explicitly",120,15 +-,TNP-4437,"(ODT-1339) User (id 511) on wv-contentpool is locked and cannot access the system.",0,30 +-,TNP-4442,(ODT-1341) Custom HTML block is not rendered,0,120 +-,TNP-4478,(ODT-1368) Hosting provider transition of all projects hosted on their OpenShift infrastructure to the new Kuberneets (k8) infrastructure.,0,90 +-,TNP-4480,(ODT-1370) Error: Call to a member function getUrl() on null / cannot save an article on stage systems,0,90 diff --git a/app/tests/data/invoice-21-03.txt b/app/tests/data/invoice-21-03.txt new file mode 100644 index 0000000..3da3ffc --- /dev/null +++ b/app/tests/data/invoice-21-03.txt @@ -0,0 +1,11 @@ +report: /home/lio/Projects/drunomix/rprt-cli/app/tests/Kernel/../data/21-03.csv ++-----------------------------+--------+-------+----------+ +| Project | Hours | Rate | Price | ++-----------------------------+--------+-------+----------+ +| lupus.digital publishing | 61,75 | 25,60 | 1.580,80 | +| Projektbezogene Entwicklung | 100,50 | 29,10 | 2.924,55 | ++-----------------------------+--------+-------+----------+ +| Gesamt netto | 162,25 | | 4.505,35 | ++-----------------------------+--------+-------+----------+ +| Gessamt brutto | 4.505,35 | ++-----------------------------+--------+-------+----------+ diff --git a/app/tests/data/report-21-03.txt b/app/tests/data/report-21-03.txt new file mode 100644 index 0000000..96d624d --- /dev/null +++ b/app/tests/data/report-21-03.txt @@ -0,0 +1,76 @@ +report: /home/lio/Projects/drunomix/rprt-cli/app/tests/Kernel/../data/21-03.csv ++----------------+--------------------------------------------------------------+------+------------+ +| Ticket Id | Name | Time | Estimation | ++----------------+--------------------------------------------------------------+------+------------+ +| DEV-46 | Wochenplanung, Weekly | 315 | 0 | +| DEV-56 | Developer training | 60 | 0 | +| DEV-122 | Daily standup | 255 | 0 | ++----------------+--------------------------------------------------------------+------+------------+ +| DEV | 10.5 | ++----------------+--------------------------------------------------------------+------+------------+ +| INF-6 | Infrastructure misc, diverse | 75 | 0 | ++----------------+--------------------------------------------------------------+------+------------+ +| INF | 1.25 | ++----------------+--------------------------------------------------------------+------+------------+ +| SND-181 | Sprint meetings (PM) | 390 | 240 | +| SND-507 | (TKT-307) Change webhook integration for Slack | 330 | 0 | +| SND-552 | (TKT-740) Allow kicking users out of collections | 45 | 780 | +| SND-554 | (TKT-1448) Adaptions in Backend | 30 | 0 | +| SND-556 | [story] (TKT-1393) Make Paragraph embedding more user friend | 75 | 0 | +| SND-558 | (TKT-1467) Full copy of article doesn't update the timestamp | 15 | 0 | +| SND-562 | (TKT-1441) Implement SEO title in BE | 45 | 0 | ++----------------+--------------------------------------------------------------+------+------------+ +| SND | 15.5 | ++----------------+--------------------------------------------------------------+------+------------+ +| LDP-668 | Add json-ld schema.org metadata to articles | 300 | 0 | +| LDP-685 | LDP-Contentpool sitemaps. Extend "simple_sitemap_extended" s | 15 | 0 | +| LDP-692 | Output json-ld script | 30 | 0 | +| LDP-693 | Add WebPage schema.org support | 180 | 120 | +| LDP-700 | LDP onboarding Somebody | 15 | 0 | +| LDP-706 | Backend FAQ Marketing Block | 165 | 0 | +| LDP-707 | Backend "Hero" Marketing Block | 1035 | 0 | +| LDP-709 | Backend "Newsletter Signup" Marketing Block | 195 | 0 | +| LDP-711 | Backend "Call to action" Marketing Block | 165 | 0 | +| LDP-712 | Backend "Feature section" Marketing Block | 300 | 0 | +| LDP-713 | Provide a field type and pre-configuration for choosing icon | 45 | 300 | +| LDP-716 | Entity browser UX is not as good as expected | 15 | 0 | +| LDP-720 | Improve display of nodes and add support for article heros | 45 | 0 | +| LDP-728 | ldp-marketing blocks break the page when they are added to t | 195 | 0 | +| LDP-729 | ldp-cp portal entity | 480 | 0 | +| LDP-740 | CP: Add portal path prefixes | 30 | 480 | +| LDP-741 | Defects marketing Blocks | 450 | 0 | +| LDP-742 | [Red Alert] Develop branch fails to build | 45 | 0 | ++----------------+--------------------------------------------------------------+------+------------+ +| LDP | 61.75 | ++----------------+--------------------------------------------------------------+------+------------+ +| TES-8 | Plan hosting setup on custom hosting provider | 45 | 0 | ++----------------+--------------------------------------------------------------+------+------------+ +| TES | 0.75 | ++----------------+--------------------------------------------------------------+------+------------+ +| TNP-31 | Internal sprint meetings (PM, fixed-price). | 150 | 0 | +| TNP-4304 | (ODT-1240) Structured data on article (satellite) pages and | 750 | 600 | +| TNP-4305 | (ODT-1202) Add mobile-banner-3 & 4 (advertisement in article | 60 | 0 | +| TNP-4326 | (ODT-1174) Make image optional in the Call to Action block | 60 | 135 | +| TNP-4355 | (ODT-1270) Add article title to breadcrumbs | 270 | 0 | +| TNP-4359 | (ODT-1254) Display the text paragraph "zwischentitel" in H2 | 90 | 0 | +| TNP-4372 | (ODT-1297) Branch analytics for articles associated with spe | 15 | 135 | +| TNP-4384 | (ODT-1306) Layout-builder rendering in Chrome browser | 120 | 120 | +| TNP-4393 | TNPsat docker build error | 90 | 0 | +| TNP-4410 | (ODT-1317) SOLR Search optimization >> suggested articles do | 30 | 375 | +| TNP-4411 | Extend simple_sitemap_extensions for dynamic variants & Inst | 2070 | 600 | +| TNP-4412 | Implement custom dynamic variants for sitemaps to group by m | 105 | 0 | +| TNP-4414 | Invalid JSON in the cache_tools composer.json file | 60 | 0 | +| TNP-4421 | TNP Satellites Hand bau image file entities are not replicat | 15 | 0 | +| TNP-4422 | [Red Alert] Behat test fail. "Demo content loaded..Error pag | 75 | 0 | +| TNP-4423 | (ODT-1325) Site managers must be able to change article stat | 15 | 0 | +| TNP-4425 | Unpublished Advertorials are returned | 30 | 0 | +| TNP-4427 | (ODT-1332) "Og: image" is not specified explicitly | 15 | 120 | +| TNP-4437 | (ODT-1339) User (id 511) on wv-contentpool is locked and can | 30 | 0 | +| TNP-4442 | (ODT-1341) Custom HTML block is not rendered | 120 | 0 | +| TNP-4478 | (ODT-1368) Hosting provider transition of all projects hoste | 90 | 0 | +| TNP-4480 | (ODT-1370) Error: Call to a member function getUrl() on null | 90 | 0 | ++----------------+--------------------------------------------------------------+------+------------+ +| TNP | 72.5 | ++----------------+--------------------------------------------------------------+------+------------+ +| DEV, INF, SND, LDP, TES, TNP | 162.25 | ++----------------+--------------------------------------------------------------+------+------------+ diff --git a/app/tests/test-dependencies.php b/app/tests/test-dependencies.php index 3675163..8424b58 100644 --- a/app/tests/test-dependencies.php +++ b/app/tests/test-dependencies.php @@ -2,6 +2,6 @@ $dependencies = require_once(__DIR__ . '/../dependencies.php'); -$dependencies['config.path'] = __DIR__ . '/data'; +$dependencies['config.path'] = __DIR__ . '/data/'; return $dependencies; diff --git a/todo.txt b/todo.txt index c8bd374..1a5e46c 100644 --- a/todo.txt +++ b/todo.txt @@ -21,8 +21,8 @@ TODO: TODO (end of 2022): - DONE fix project list output (first is missing) - DONE report selection trait -- automated tests -- phpcs +- DONE automated tests +- DONE phpcs - phpstan OPTIONAL: - phing build system to run quality assurance