Completed
Pull Request — master (#439)
by
unknown
01:56
created

ImportCommandController::execute()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 54
rs 9.0036
c 0
b 0
f 0
cc 4
nc 4
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Import.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Calendarize\Command;
9
10
use HDNET\Calendarize\Service\IndexerService;
11
use Symfony\Component\Console\Command\Command;
12
use Symfony\Component\Console\Input\InputArgument;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Console\Style\SymfonyStyle;
16
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
18
use TYPO3\CMS\Core\Utility\MathUtility;
19
use TYPO3\CMS\Extbase\SignalSlot\Dispatcher;
20
21
/**
22
 * Import.
23
 */
24
class ImportCommandController extends Command
25
{
26
    protected function configure()
27
    {
28
        $this->setDescription('Imports a iCalendar ICS into a page ID')
29
            ->addArgument('icsCalendarUri', InputArgument::REQUIRED, 'The URI of the iCalendar ICS')
30
            ->addArgument('pid', InputArgument::REQUIRED, 'The page ID to create new elements');
31
    }
32
33
    /**
34
     * Executes the command for importing a iCalendar ICS into a page ID.
35
     *
36
     * @param InputInterface $input
37
     * @param OutputInterface $output
38
     * @return int 0 if everything went fine, or an exit code
39
     */
40
    protected function execute(InputInterface $input, OutputInterface $output)
41
    {
42
        $io = new SymfonyStyle($input, $output);
43
44
        $icsCalendarUri = $input->getArgument('icsCalendarUri');
45
        $pid = $input->getArgument('pid');
46
47
        if (!\filter_var($icsCalendarUri, FILTER_VALIDATE_URL)) {
48
            $io->error('You have to enter a valid URL to the iCalendar ICS');
49
50
            return 1;
51
        }
52
        if (!MathUtility::canBeInterpretedAsInteger($pid)) {
53
            $io->error('You have to enter a valid PID for the new created elements');
54
55
            return 2;
56
        }
57
        $pid = (int)$pid;
58
59
        // fetch external URI and write to file
60
        $io->section('Start to checkout the calendar: ' . $icsCalendarUri);
61
        $relativeIcalFile = 'typo3temp/ical.' . GeneralUtility::shortMD5($icsCalendarUri) . '.ical';
0 ignored issues
show
Bug introduced by
It seems like $icsCalendarUri defined by $input->getArgument('icsCalendarUri') on line 44 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...
62
        $absoluteIcalFile = GeneralUtility::getFileAbsFileName($relativeIcalFile);
63
        $content = GeneralUtility::getUrl($icsCalendarUri);
0 ignored issues
show
Bug introduced by
It seems like $icsCalendarUri defined by $input->getArgument('icsCalendarUri') on line 44 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...
64
        GeneralUtility::writeFile($absoluteIcalFile, $content);
65
66
        // get Events from file
67
        $icalEvents = $this->getIcalEvents($absoluteIcalFile);
68
        $events = $this->prepareEvents($icalEvents, $io);
69
70
        $io->text('Found ' . \count($events) . ' events in ' . $icsCalendarUri);
71
72
        $signalSlotDispatcher = GeneralUtility::makeInstance(Dispatcher::class);
73
74
        $io->section('Send the ' . __CLASS__ . '::importCommand signal for each event.');
75
        $io->progressStart(\count($events));
76
        foreach ($events as $event) {
77
            $arguments = [
78
                'event' => $event,
79
                'io' => $io,
80
                'pid' => $pid,
81
                'handled' => false,
82
            ];
83
            $signalSlotDispatcher->dispatch(__CLASS__, 'importCommand', $arguments);
84
            $io->progressAdvance();
85
        }
86
        $io->progressFinish();
87
88
        $io->section('Run Reindex proces after import');
89
        $indexer = GeneralUtility::makeInstance(IndexerService::class);
90
        $indexer->reindexAll();
91
92
        return 0;
93
    }
94
95
    /**
96
     * Prepare the events.
97
     *
98
     * @param array $icalEvents
99
     *
100
     * @param SymfonyStyle $io
101
     * @return array
102
     */
103
    protected function prepareEvents(array $icalEvents, SymfonyStyle $io)
104
    {
105
        $events = [];
106
        foreach ($icalEvents as $icalEvent) {
107
            $startDateTime = null;
108
            $endDateTime = null;
109
            try {
110
                $startDateTime = new \DateTime($icalEvent['DTSTART']);
111
                if ($icalEvent['DTEND']) {
112
                    $endDateTime = new \DateTime($icalEvent['DTEND']);
113
                } else {
114
                    $endDateTime = clone $startDateTime;
115
                    $endDateTime->add(new \DateInterval($icalEvent['DURATION']));
116
                }
117
            } catch (\Exception $ex) {
118
                $io->warning('Could not convert the date in the right format of "' . $icalEvent['SUMMARY'] . '"');
119
                continue;
120
            }
121
122
            $events[] = [
123
                'uid' => $icalEvent['UID'],
124
                'start' => $startDateTime,
125
                'end' => $endDateTime,
126
                'title' => $icalEvent['SUMMARY'] ? $icalEvent['SUMMARY'] : '',
127
                'description' => $icalEvent['DESCRIPTION'] ? $icalEvent['DESCRIPTION'] : '',
128
                'location' => $icalEvent['LOCATION'] ? $icalEvent['LOCATION'] : '',
129
            ];
130
        }
131
132
        return $events;
133
    }
134
135
    /**
136
     * Get the events from the given ical file.
137
     *
138
     * @param string $absoluteIcalFile
139
     *
140
     * @return array
141
     */
142
    protected function getIcalEvents($absoluteIcalFile)
143
    {
144
        if (!\class_exists('ICal')) {
145
            require_once ExtensionManagementUtility::extPath(
146
                'calendarize',
147
                'Resources/Private/Php/ics-parser/class.iCalReader.php'
148
            );
149
        }
150
151
        return (array)(new \ICal($absoluteIcalFile))->events();
152
    }
153
}
154