Completed
Pull Request — master (#443)
by
unknown
03:08
created

ImportCommandController::getIcalEvents()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
/**
4
 * Import.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Calendarize\Command;
9
10
use HDNET\Calendarize\Event\ImportSingleIcalEvent;
11
use HDNET\Calendarize\Service\Ical\ICalServiceInterface;
12
use HDNET\Calendarize\Service\IndexerService;
13
use HDNET\Calendarize\Utility\DateTimeUtility;
14
use Psr\EventDispatcher\EventDispatcherInterface;
15
use Symfony\Component\Console\Command\Command;
16
use Symfony\Component\Console\Input\InputArgument;
17
use Symfony\Component\Console\Input\InputInterface;
18
use Symfony\Component\Console\Input\InputOption;
19
use Symfony\Component\Console\Output\OutputInterface;
20
use Symfony\Component\Console\Style\SymfonyStyle;
21
use TYPO3\CMS\Core\Core\Environment;
22
use TYPO3\CMS\Core\Utility\GeneralUtility;
23
use TYPO3\CMS\Core\Utility\MathUtility;
24
25
/**
26
 * Import.
27
 */
28
class ImportCommandController extends Command
29
{
30
31
    /**
32
     * @var ICalServiceInterface $iCalService
33
     */
34
    protected $iCalService;
35
36
    /**
37
     * @var EventDispatcherInterface
38
     */
39
    protected $eventDispatcher;
40
41
    /**
42
     * @var IndexerService
43
     */
44
    protected $indexerService;
45
46
    /**
47
     * ImportCommandController constructor.
48
     * @param string|null $name
49
     * @param ICalServiceInterface $iCalService
50
     * @param EventDispatcherInterface $eventDispatcher
51
     * @param IndexerService $indexerService
52
     */
53
    public function __construct(
54
        string $name = null,
55
        ICalServiceInterface $iCalService,
56
        EventDispatcherInterface $eventDispatcher,
57
        IndexerService $indexerService
58
    ) {
59
        $this->iCalService = $iCalService;
60
        $this->eventDispatcher = $eventDispatcher;
61
        $this->indexerService = $indexerService;
62
63
        parent::__construct($name);
64
    }
65
66
    protected function configure()
67
    {
68
        $this->setDescription('Imports a iCalendar ICS into a page ID')
69
            ->addArgument(
70
                'icsCalendarUri',
71
                InputArgument::REQUIRED,
72
                'The URI of the iCalendar ICS'
73
            )
74
            ->addArgument(
75
                'pid',
76
                InputArgument::REQUIRED,
77
                'The page ID to create new elements'
78
            )
79
            ->addOption(
80
                'since',
81
                's',
82
                InputOption::VALUE_OPTIONAL,
83
                "Imports all events since the given date.\n"
84
                . 'Valid PHP date format e.g. "2014-04-14", "-10 days" (Note: use --since="-x days" syntax)',
85
                DateTimeUtility::getNow()->format('Y-m-d')
86
            );
87
    }
88
89
    /**
90
     * Executes the command for importing a iCalendar ICS into a page ID.
91
     *
92
     * @param InputInterface $input
93
     * @param OutputInterface $output
94
     * @return int 0 if everything went fine, or an exit code
95
     * @throws \Exception
96
     */
97
    protected function execute(InputInterface $input, OutputInterface $output)
98
    {
99
        $io = new SymfonyStyle($input, $output);
100
101
        $icsCalendarUri = $input->getArgument('icsCalendarUri');
102
        if (!GeneralUtility::isValidUrl($icsCalendarUri)) {
0 ignored issues
show
Bug introduced by
It seems like $icsCalendarUri defined by $input->getArgument('icsCalendarUri') on line 101 can also be of type array<integer,string> or null; however, TYPO3\CMS\Core\Utility\G...alUtility::isValidUrl() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
103
            $io->error('You have to enter a valid URL to the iCalendar ICS');
104
            return 1;
105
        }
106
107
        $pid = $input->getArgument('pid');
108
        if (!MathUtility::canBeInterpretedAsInteger($pid)) {
109
            $io->error('You have to enter a valid PID for the new created elements');
110
            return 1;
111
        }
112
        $pid = (int)$pid;
113
114
        // Process skip
115
        $since = $input->getOption('since');
116
        $ignoreBeforeDate = null;
117
        if ($since !== null) {
118
            $ignoreBeforeDate = new \DateTime($since);
119
            $io->text('Skipping all events before ' . $ignoreBeforeDate->format(\DateTimeInterface::ATOM));
120
        }
121
122
        // Fetch external URI and write it to a temporary file
123
        $io->section('Start to checkout the calendar');
124
125
        $content = GeneralUtility::getUrl($icsCalendarUri);
0 ignored issues
show
Bug introduced by
It seems like $icsCalendarUri defined by $input->getArgument('icsCalendarUri') on line 101 can also be of type array<integer,string> or null; however, TYPO3\CMS\Core\Utility\GeneralUtility::getUrl() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
126
        if ($content === false) {
127
            $io->error('Unable to get the content of ' . $icsCalendarUri . '.');
128
            return 1;
129
        }
130
131
        $icalFile = Environment::getVarPath() . '/transient/.' . 'ical-' . GeneralUtility::shortMD5($icsCalendarUri) . '.ics';
0 ignored issues
show
Bug introduced by
It seems like $icsCalendarUri defined by $input->getArgument('icsCalendarUri') on line 101 can also be of type array<integer,string> or null; however, TYPO3\CMS\Core\Utility\GeneralUtility::shortMD5() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
132
        $tempResult = GeneralUtility::writeFileToTypo3tempDir($icalFile, $content);
133
        if ($tempResult !== null) {
134
            $io->error('Unable to write to "' . $icalFile . '". Reason: ' . $tempResult);
135
            return 1;
136
        }
137
138
        // Parse calendar
139
        $events = $this->iCalService->getEvents($icalFile);
140
141
        // Remove temporary file
142
        unlink($icalFile);
143
144
        $io->text('Found ' . \count($events) . ' events in ' . $icsCalendarUri);
145
146
        $io->section('Send ImportSingleIcalEvent for each event');
147
        $io->progressStart(\count($events));
148
149
        $skipCount = $dispatchCount = 0;
150
        foreach ($events as $event) {
151
            // Skip events before given date
152
            if (($event->getEndDate() ?? $event->getStartDate()) < $ignoreBeforeDate) {
153
                $io->progressAdvance();
154
                $skipCount++;
155
                continue;
156
            }
157
158
            $this->eventDispatcher->dispatch(new ImportSingleIcalEvent($event, $pid));
0 ignored issues
show
Documentation introduced by
new \HDNET\Calendarize\E...IcalEvent($event, $pid) is of type object<HDNET\Calendarize...\ImportSingleIcalEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
159
            $dispatchCount++;
160
            $io->progressAdvance();
161
        }
162
        $io->progressFinish();
163
164
        $io->text('Dispatched ' . $dispatchCount . ' Events');
165
        $io->text('Skipped ' . $skipCount . ' Events');
166
167
        $io->section('Run Reindex process after import');
168
        $this->indexerService->reindexAll();
169
170
        return 0;
171
    }
172
}
173