Add pdf export.
parent
9cf4d23012
commit
e605729aaf
|
@ -69,5 +69,5 @@
|
||||||
|
|
||||||
*** Get csv file
|
*** Get csv file
|
||||||
|
|
||||||
curl 'https://drunomics.myjetbrains.com/youtrack/api/reports/83-554/export/csv?&$top=-1' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H "Authorization: Bearer $TKN" > ~/Documents/Drunomics/workhours/2021/21-09.csv
|
~curl 'https://drunomics.myjetbrains.com/youtrack/api/reports/83-554/export/csv?&$top=-1' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H "Authorization: Bearer $TKN" > ~/Documents/Drunomics/workhours/2021/21-09.csv~
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 10pt;
|
||||||
|
}
|
||||||
|
p { margin: 0pt; }
|
||||||
|
td { vertical-align: top; }
|
||||||
|
.items td {
|
||||||
|
border-left: 0.1mm solid #000000;
|
||||||
|
border-right: 0.1mm solid #000000;
|
||||||
|
}
|
||||||
|
table thead td { background-color: #EEEEEE;
|
||||||
|
text-align: center;
|
||||||
|
border: 0.1mm solid #000000;
|
||||||
|
font-variant: small-caps;
|
||||||
|
}
|
||||||
|
.items td.blanktotal {
|
||||||
|
background-color: #EEEEEE;
|
||||||
|
border: 0.1mm solid #000000;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border: 0mm none #000000;
|
||||||
|
border-top: 0.1mm solid #000000;
|
||||||
|
border-right: 0.1mm solid #000000;
|
||||||
|
}
|
||||||
|
.items td.totals {
|
||||||
|
text-align: right;
|
||||||
|
border: 0.1mm solid #000000;
|
||||||
|
}
|
||||||
|
.items td.cost,
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class="center">My company name</br>My company address</br>123456789, mycompany@email.com</br>987654321</p>
|
||||||
|
<p></p>
|
||||||
|
<p>Other company</br>Other company address</br>1111 City</br>State</p>
|
||||||
|
<p></p>
|
||||||
|
<p></p>
|
||||||
|
<p></p>
|
||||||
|
<p class="right">City, on 20. 9. 2021</p>
|
||||||
|
<p><strong>Honorarnote</br>Nummer [[number]]</strong></p>
|
||||||
|
<p></p>
|
||||||
|
<p>Für meine Tätigkeit Programmieren von [[date_start]] bis [[date_end]] erlaube ich mir, folgenden Betrag in Rechnung zu stellen:</p>
|
||||||
|
[[table]]
|
||||||
|
<p>Ich ersuche Sie höflich, den oben angeführt auf meine Kontonummer [[account_number]] mit der Bankleitzahl ABCDSI33 zu überweisen.</p>
|
||||||
|
<p>Vielen Dank für den Auftrag,</br>
|
||||||
|
mit besten Grüßen,</p>
|
||||||
|
<p></p>
|
||||||
|
<p></p>
|
||||||
|
<p>My name</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,9 +1,22 @@
|
||||||
##########################################
|
##########################################
|
||||||
# Configuration file for RprtCli Command #
|
# Configuration file for RprtCli Command #
|
||||||
##########################################
|
##########################################
|
||||||
tracking service:
|
tracking_service:
|
||||||
youtrack:
|
youtrack:
|
||||||
auth token: '<value from youtrack hub>'
|
auth_token: '<value from youtrack hub>'
|
||||||
|
base_url: 'https://test.youtrack.com'
|
||||||
|
report_id: '<89-123>'
|
||||||
|
export:
|
||||||
|
template_path: '~/.config/rprt-cli/invoice-template.html'
|
||||||
|
output: '/tmp/YYYY-mm-invoice.pdf'
|
||||||
|
tokens:
|
||||||
|
key: 'value to replace key'
|
||||||
|
another_key: 'value to replace another key'
|
||||||
|
labels:
|
||||||
|
- 'Project'
|
||||||
|
- 'Hours'
|
||||||
|
- 'Rate'
|
||||||
|
- 'Price'
|
||||||
# reports:
|
# reports:
|
||||||
# report short name:
|
# report short name:
|
||||||
# table:
|
# table:
|
||||||
|
@ -21,10 +34,5 @@ projects:
|
||||||
time column: 4
|
time column: 4
|
||||||
# time format m - minutes, h - hours
|
# time format m - minutes, h - hours
|
||||||
time format: 'm'
|
time format: 'm'
|
||||||
labels:
|
|
||||||
project: Project
|
|
||||||
# hours: Quantity
|
|
||||||
hours: Hours
|
|
||||||
rate: 'Price per hour'
|
|
||||||
price: Price
|
|
||||||
locale: 'en_GB'
|
locale: 'en_GB'
|
||||||
|
|
|
@ -9,6 +9,9 @@ use RprtCli\Utils\Configuration\ConfigurationService;
|
||||||
use RprtCli\Utils\CsvReport\CsvReport;
|
use RprtCli\Utils\CsvReport\CsvReport;
|
||||||
use RprtCli\Utils\CsvReport\CsvReportInterface;
|
use RprtCli\Utils\CsvReport\CsvReportInterface;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
|
use Mpdf\Mpdf;
|
||||||
|
use RprtCli\Utils\PdfExport\PdfExportInterface;
|
||||||
|
use RprtCli\Utils\PdfExport\PdfExportService;
|
||||||
use RprtCli\Utils\TimeTrackingServices\YoutrackInterface;
|
use RprtCli\Utils\TimeTrackingServices\YoutrackInterface;
|
||||||
use RprtCli\Utils\TimeTrackingServices\YoutrackService;
|
use RprtCli\Utils\TimeTrackingServices\YoutrackService;
|
||||||
|
|
||||||
|
@ -22,6 +25,7 @@ return [
|
||||||
// 'translator' => ['default_path' => '%kernel.project_dir%/translations'],
|
// 'translator' => ['default_path' => '%kernel.project_dir%/translations'],
|
||||||
// 'guzzle' => create()->constructor(Client::class),
|
// 'guzzle' => create()->constructor(Client::class),
|
||||||
'guzzle' => get(Client::class),
|
'guzzle' => get(Client::class),
|
||||||
|
'mpdf' => get(Mpdf::class),
|
||||||
ConfigurationInterface::class => get(ConfigurationService::class),
|
ConfigurationInterface::class => get(ConfigurationService::class),
|
||||||
ConfigurationService::class => create()->constructor(
|
ConfigurationService::class => create()->constructor(
|
||||||
get('config.path'),
|
get('config.path'),
|
||||||
|
@ -34,6 +38,12 @@ return [
|
||||||
get('guzzle')
|
get('guzzle')
|
||||||
),
|
),
|
||||||
'youtrack.service' => get(YoutrackInterface::class),
|
'youtrack.service' => get(YoutrackInterface::class),
|
||||||
|
PdfExportInterface::class => get(PdfExportService::class),
|
||||||
|
PdfExportService::class => create()->constructor(
|
||||||
|
get('config.service'),
|
||||||
|
get('mpdf')
|
||||||
|
),
|
||||||
|
'pdf_export.service' => get(PdfExportInterface::class),
|
||||||
// 'locale' => get('config.service')->method('get', 'en'),
|
// 'locale' => get('config.service')->method('get', 'en'),
|
||||||
// Translator::class => create()->constructor('sl')->method('addLoader', 'po', new PoFileLoader),
|
// Translator::class => create()->constructor('sl')->method('addLoader', 'po', new PoFileLoader),
|
||||||
// 'translator' => get(Translator::class),
|
// 'translator' => get(Translator::class),
|
||||||
|
@ -45,6 +55,7 @@ return [
|
||||||
RprtCommand::class => create()->constructor(
|
RprtCommand::class => create()->constructor(
|
||||||
get('csv.report'),
|
get('csv.report'),
|
||||||
get('config.service'),
|
get('config.service'),
|
||||||
get('youtrack.service')
|
get('youtrack.service'),
|
||||||
|
get('pdf_export.service')
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace RprtCli\Commands;
|
||||||
|
|
||||||
use RprtCli\Utils\Configuration\ConfigurationInterface;
|
use RprtCli\Utils\Configuration\ConfigurationInterface;
|
||||||
use RprtCli\Utils\CsvReport\CsvReportInterface;
|
use RprtCli\Utils\CsvReport\CsvReportInterface;
|
||||||
|
use RprtCli\Utils\PdfExport\PdfExportInterface;
|
||||||
use RprtCli\Utils\TimeTrackingServices\YoutrackInterface;
|
use RprtCli\Utils\TimeTrackingServices\YoutrackInterface;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Helper\Table;
|
use Symfony\Component\Console\Helper\Table;
|
||||||
|
@ -30,15 +31,19 @@ class RprtCommand extends Command
|
||||||
|
|
||||||
protected $youtrack;
|
protected $youtrack;
|
||||||
|
|
||||||
|
protected $pdfExport;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
CsvReportInterface $csv,
|
CsvReportInterface $csv,
|
||||||
ConfigurationInterface $configuration,
|
ConfigurationInterface $configuration,
|
||||||
YoutrackInterface $youtrack,
|
YoutrackInterface $youtrack,
|
||||||
|
PdfExportInterface $pdf_export,
|
||||||
?string $name = null
|
?string $name = null
|
||||||
) {
|
) {
|
||||||
$this->csv = $csv;
|
$this->csv = $csv;
|
||||||
$this->configuration = $configuration;
|
$this->configuration = $configuration;
|
||||||
$this->youtrack = $youtrack;
|
$this->youtrack = $youtrack;
|
||||||
|
$this->pdfExport = $pdf_export;
|
||||||
parent::__construct($name);
|
parent::__construct($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,10 +87,23 @@ class RprtCommand extends Command
|
||||||
$test = $this->youtrack->testYoutrackapi();
|
$test = $this->youtrack->testYoutrackapi();
|
||||||
$output->writeln($test);
|
$output->writeln($test);
|
||||||
}
|
}
|
||||||
if ($file = $input->getOption('file')) {
|
if ($youtrack = $input->getOption('youtrack')) {
|
||||||
|
$report_id = $this->youtrack->getReportId();
|
||||||
|
$file = $this->youtrack->downloadReport($report_id);
|
||||||
|
}
|
||||||
|
if ($youtrack || $file = $input->getOption('file')) {
|
||||||
|
// Youtrack can also provide a file name.
|
||||||
|
var_dump($file);
|
||||||
$data = $this->csv->getReportData($file);
|
$data = $this->csv->getReportData($file);
|
||||||
$table = $this->generateTable($output, $data);
|
$table = $this->generateTable($output, $data);
|
||||||
$table->render();
|
$table->render();
|
||||||
|
|
||||||
|
if ($pdf = $input->getOption('pdf')) {
|
||||||
|
$nice_data = $this->csv->arangeDataForPdfExport($data);
|
||||||
|
// @TODO method gatherTokens();
|
||||||
|
$this->pdfExport->fromDataToPdf($nice_data);
|
||||||
|
}
|
||||||
|
|
||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,9 +58,10 @@ class CsvReport implements CsvReportInterface
|
||||||
/**
|
/**
|
||||||
* Get correct values from the raw data lines of csv.
|
* Get correct values from the raw data lines of csv.
|
||||||
*
|
*
|
||||||
*
|
* @param array $rawData
|
||||||
* Columns with data are specified in config.
|
* Columns with data are specified in config.
|
||||||
*
|
*
|
||||||
|
* @return array
|
||||||
* Project key and unit of time spent.
|
* Project key and unit of time spent.
|
||||||
*/
|
*/
|
||||||
protected function parseCsvFile(array $rawData) : array
|
protected function parseCsvFile(array $rawData) : array
|
||||||
|
@ -74,6 +75,41 @@ class CsvReport implements CsvReportInterface
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function arangeDataForPdfExport(array $data): array {
|
||||||
|
[$rows, $totalHours, $totalPrice] = [[], 0, 0];
|
||||||
|
$projectsConfig = $this->configurationService->get('projects');
|
||||||
|
$header = $this->configurationService->get('export.labels', null);
|
||||||
|
if (is_array($header)) {
|
||||||
|
$rows[] = $header;
|
||||||
|
}
|
||||||
|
foreach ($projectsConfig as $name => $config) {
|
||||||
|
if (! isset($data[$name])) {
|
||||||
|
// @TODO Proper error handling.
|
||||||
|
var_dump('Project ' . $name . ' is not set!');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$hours = $data[$name];
|
||||||
|
if ($config['time_format'] === 'm') {
|
||||||
|
$hours /= 60;
|
||||||
|
}
|
||||||
|
$price = $hours * (int) $config['price'];
|
||||||
|
$row = [
|
||||||
|
$config['name'],
|
||||||
|
$hours,
|
||||||
|
$config['price'],
|
||||||
|
$hours * $config['price'],
|
||||||
|
];
|
||||||
|
$rows[] = $row;
|
||||||
|
$totalHours += $hours;
|
||||||
|
$totalPrice += $price;
|
||||||
|
}
|
||||||
|
// @TODO Check rate in final result.
|
||||||
|
// $rows[] = [$this->translator->trans('Sum'), $totalHours, $config['price'], $totalPrice];
|
||||||
|
$rows[] = ['Sum', $totalHours, $config['price'], $totalPrice];
|
||||||
|
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
|
||||||
protected function dummyConfig() : array
|
protected function dummyConfig() : array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace RprtCli\Utils\PdfExport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles exporting parsed csv data to pdf files.
|
||||||
|
*/
|
||||||
|
interface PdfExportInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves path to template file either from command option, configuration
|
||||||
|
* or from uer input.
|
||||||
|
*/
|
||||||
|
public function getTemplatePath(): ?string;
|
||||||
|
|
||||||
|
public function setTemplatePath(string $path): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates html table from parsed csv data.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* First line is header. The rest of them is table body.
|
||||||
|
*/
|
||||||
|
public function parsedDataToHtmlTable(array $data): ?string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the template file and replaces token values.
|
||||||
|
*/
|
||||||
|
public function replaceTokensInTemplate(string $template_path, array $tokens): ?string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and export file.
|
||||||
|
*
|
||||||
|
* @param string $html
|
||||||
|
* Template file with tokens replaced.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* True if export was successfull.
|
||||||
|
*/
|
||||||
|
public function pdfExport(string $html) : bool;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace RprtCli\Utils\PdfExport;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use RprtCli\Utils\Configuration\ConfigurationInterface;
|
||||||
|
use Mpdf\Output\Destination;
|
||||||
|
|
||||||
|
class PdfExportService implements PdfExportInterface {
|
||||||
|
|
||||||
|
protected $templatePath;
|
||||||
|
protected $output;
|
||||||
|
|
||||||
|
protected $config;
|
||||||
|
|
||||||
|
protected $mpdf;
|
||||||
|
|
||||||
|
public function __construct(ConfigurationInterface $config, $mpdf) {
|
||||||
|
$this->config = $config;
|
||||||
|
$this->mpdf = $mpdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTemplatePath(): ?string
|
||||||
|
{
|
||||||
|
if (!isset($this->templatePath)) {
|
||||||
|
$template_path = $this->config->get('report.template_path', FALSE);
|
||||||
|
if (!$template_path) {
|
||||||
|
$template_path = readline('Enter template file path: ');
|
||||||
|
}
|
||||||
|
if (!file_exists($template_path)) {
|
||||||
|
throw new Exception('Template file not found!');
|
||||||
|
}
|
||||||
|
$this->templatePath = $template_path;
|
||||||
|
}
|
||||||
|
return $this->templatePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTemplatePath(string $path): void {
|
||||||
|
if (file_exists($path)) {
|
||||||
|
$this->templatePath = $path;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception('Template file not found!');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parsedDataToHtmlTable(array $data): ?string {
|
||||||
|
$table = '<table><thead><tr>';
|
||||||
|
$header = array_shift($data);
|
||||||
|
foreach ($header as $cell) {
|
||||||
|
$table .= "<th>{$cell}</th>";
|
||||||
|
}
|
||||||
|
$table .= '</tr></thead><tbody>';
|
||||||
|
foreach ($data as $row) {
|
||||||
|
$cells = [];
|
||||||
|
foreach ($row as $cell) {
|
||||||
|
$cells[] = "<td>{$cell}</td>";
|
||||||
|
}
|
||||||
|
$rows[] = '<tr>' . implode($cells) . '</tr>';
|
||||||
|
}
|
||||||
|
$table .= implode('', $rows);
|
||||||
|
$table .= '</tbody></table>';
|
||||||
|
return $table;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function replaceTokensInTemplate(string $template_path, array $tokens): ?string
|
||||||
|
{
|
||||||
|
$template = file_get_contents($template_path);
|
||||||
|
foreach ($tokens as $key => $value) {
|
||||||
|
$template = str_replace("[[{$key}]]", $value, $template);
|
||||||
|
}
|
||||||
|
return $template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pdfExport(string $html, $output = null): bool {
|
||||||
|
$this->mpdf->SetProtection(array('print'));
|
||||||
|
$this->mpdf->SetTitle("Acme Trading Co. - Invoice");
|
||||||
|
$this->mpdf->SetAuthor("Acme Trading Co.");
|
||||||
|
$this->mpdf->SetDisplayMode('fullpage');
|
||||||
|
|
||||||
|
$this->mpdf->WriteHTML($html);
|
||||||
|
|
||||||
|
if (!$this->output) {
|
||||||
|
$this->output = $this->config->get('report.output', NULL) ?? readline('Enter output file path: ');
|
||||||
|
}
|
||||||
|
$this->mpdf->Output($this->output, Destination::FILE);
|
||||||
|
return file_exists($this->output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOutput(string $path) {
|
||||||
|
$this->output = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fromDataToPdf(array $data, array $tokens = []): bool {
|
||||||
|
$template_path = $this->getTemplatePath();
|
||||||
|
$tokens['table'] = $this->parsedDataToHtmlTable($data);
|
||||||
|
$html = $this->replaceTokensInTemplate($template_path, $tokens);
|
||||||
|
$success = $this->pdfExport($html);
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -12,6 +12,9 @@ use RprtCli\Utils\Configuration\ConfigurationInterface;
|
||||||
class YoutrackService implements YoutrackInterface
|
class YoutrackService implements YoutrackInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
|
protected $ytToken;
|
||||||
|
protected $ytBaseUrl;
|
||||||
|
|
||||||
protected $config;
|
protected $config;
|
||||||
|
|
||||||
protected $httpClient;
|
protected $httpClient;
|
||||||
|
@ -51,7 +54,7 @@ class YoutrackService implements YoutrackInterface
|
||||||
{
|
{
|
||||||
// --report option value should take precedence.
|
// --report option value should take precedence.
|
||||||
// @TODO error handling.
|
// @TODO error handling.
|
||||||
$yt_report_id = $this->config->get('youtrack.report_id');
|
$yt_report_id = $this->config->get('tracking_service.youtrack.report_id');
|
||||||
if (!$yt_report_id) {
|
if (!$yt_report_id) {
|
||||||
$yt_report_id = readline('Enter the report id: ');
|
$yt_report_id = readline('Enter the report id: ');
|
||||||
}
|
}
|
||||||
|
@ -81,6 +84,9 @@ class YoutrackService implements YoutrackInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getYtToken(): string {
|
protected function getYtToken(): string {
|
||||||
|
if (isset($this->ytToken)) {
|
||||||
|
return $this->ytToken;
|
||||||
|
}
|
||||||
$yt_token = $this->config->get('tracking_service.youtrack.auth_token', FALSE); //
|
$yt_token = $this->config->get('tracking_service.youtrack.auth_token', FALSE); //
|
||||||
if (!$yt_token) {
|
if (!$yt_token) {
|
||||||
$yt_token = readline('Enter your youtrack authentication token: ');
|
$yt_token = readline('Enter your youtrack authentication token: ');
|
||||||
|
@ -88,9 +94,18 @@ class YoutrackService implements YoutrackInterface
|
||||||
return $yt_token;
|
return $yt_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setYtToken(string $token): void {
|
||||||
|
$this->ytToken = $token;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getYtUrl(string $path = ''): ?string {
|
protected function getYtUrl(string $path = ''): ?string {
|
||||||
$yt_base_url = $this->config->get('tracking_service.youtrack.base_url', FALSE);
|
if (isset($this->ytBaseUrl)) {
|
||||||
if (!$yt_base_url) {
|
$yt_base_url = $this->ytBaseUrl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$yt_base_url = $this->config->get('tracking_service.youtrack.base_url', FALSE);
|
||||||
|
}
|
||||||
|
if (empty($yt_base_url)) {
|
||||||
$yt_base_url = readline('Enter base url for of the youtrack service: ');
|
$yt_base_url = readline('Enter base url for of the youtrack service: ');
|
||||||
}
|
}
|
||||||
if (!empty($path)) {
|
if (!empty($path)) {
|
||||||
|
@ -98,4 +113,8 @@ class YoutrackService implements YoutrackInterface
|
||||||
}
|
}
|
||||||
return $yt_base_url;
|
return $yt_base_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setYtUrl(string $base_url) {
|
||||||
|
$this->ytBaseUrl = $base_url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue