Passed
Branch main (b0ee7b)
by Gaetano
09:00
created

WorkflowCommand   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 151
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 92
c 2
b 0
f 1
dl 0
loc 151
rs 10
wmc 28

2 Methods

Rating   Name   Duplication   Size   Complexity  
F execute() 0 114 27
A configure() 0 12 1
1
<?php
2
3
namespace Kaliop\eZWorkflowEngineBundle\Command;
4
5
use Symfony\Component\Console\Input\InputInterface;
6
use Symfony\Component\Console\Output\OutputInterface;
7
use Symfony\Component\Console\Input\InputOption;
8
use Symfony\Component\Console\Input\InputArgument;
9
use Kaliop\eZMigrationBundle\API\Value\Migration;
10
use Kaliop\eZMigrationBundle\API\Value\MigrationDefinition;
11
12
/**
13
 * Command to manipulate existing workflows.
14
 */
15
class WorkflowCommand extends AbstractCommand
16
{
17
    /**
18
     * Set up the command.
19
     *
20
     * Define the name, options and help text.
21
     */
22
    protected function configure()
23
    {
24
        parent::configure();
25
26
        $this
27
            ->setName('kaliop:workflows:workflow')
28
            ->setDescription('Manually delete workflows from the database table.')
29
            ->addOption('delete', null, InputOption::VALUE_NONE, "Delete the specified workflow.")
30
            ->addOption('info', null, InputOption::VALUE_NONE, "Get info about the specified workflow.")
31
            ->addOption('no-interaction', 'n', InputOption::VALUE_NONE, "Do not ask any interactive question.")
32
            ->addArgument('workflow', InputArgument::REQUIRED, 'The workflow to view or delete (plain workflow name).', null)
33
            ->setHelp(<<<EOT
34
The <info>kaliop:workflows:workflow</info> command allows you to manually delete dead workflows from the database table:
35
36
    <info>./ezpublish/console kaliop:workflows:workflow --delete workflow_name</info>
37
38
As well as viewing details:
39
40
    <info>./ezpublish/console kaliop:workflows:workflow --info workflow_name</info>
41
EOT
42
            );
43
    }
44
45
    /**
46
     * Execute the command.
47
     *
48
     * @param InputInterface $input
49
     * @param OutputInterface $output
50
     * @return null|int null or 0 if everything went fine, or an error code
51
     */
52
    protected function execute(InputInterface $input, OutputInterface $output)
53
    {
54
        if (!$input->getOption('delete') && !$input->getOption('info')) {
55
            throw new \InvalidArgumentException('You must specify whether you want to --delete or --info the specified workflow.');
56
        }
57
58
        $workflowService = $this->getWorkflowService();
59
        $workflowNameOrPath = $input->getArgument('workflow');
60
61
        if ($input->getOption('info')) {
62
            $output->writeln('');
63
64
            $workflow = $workflowService->getWorkflow($workflowNameOrPath);
65
            if ($workflow == null) {
66
                throw new \InvalidArgumentException(sprintf('The workflow "%s" does not exist in the database table.', $workflowNameOrPath));
0 ignored issues
show
Bug introduced by
It seems like $workflowNameOrPath can also be of type string[]; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

66
                throw new \InvalidArgumentException(sprintf('The workflow "%s" does not exist in the database table.', /** @scrutinizer ignore-type */ $workflowNameOrPath));
Loading history...
67
            }
68
69
            switch ($workflow->status) {
70
                case Migration::STATUS_DONE:
71
                    $status = '<info>executed</info>';
72
                    break;
73
                case Migration::STATUS_STARTED:
74
                    $status = '<comment>execution started</comment>';
75
                    break;
76
                case Migration::STATUS_TODO:
77
                    // bold to-migrate!
78
                    $status = '<error>not executed</error>';
79
                    break;
80
                case Migration::STATUS_SKIPPED:
81
                    $status = '<comment>skipped</comment>';
82
                    break;
83
                case Migration::STATUS_PARTIALLY_DONE:
84
                    $status = '<comment>partially executed</comment>';
85
                    break;
86
                case Migration::STATUS_SUSPENDED:
87
                    $status = '<comment>suspended</comment>';
88
                    break;
89
                case Migration::STATUS_FAILED:
90
                    $status = '<error>failed</error>';
91
                    break;
92
            }
93
94
            $output->writeln('<info>Workflow: ' . $workflow->name . '</info>');
95
            $output->writeln('Status: ' . $status);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $status does not seem to be defined for all execution paths leading up to this point.
Loading history...
96
            $output->writeln('Executed on: <info>' . ($workflow->executionDate != null ? date("Y-m-d H:i:s", $workflow->executionDate) : '--'). '</info>');
97
            $output->writeln('Execution notes: <info>' . $workflow->executionError . '</info>');
98
            $output->writeln('Signal: <info>' . $workflow->signalName . '</info>');
99
100
            if ($workflow->status == Migration::STATUS_SUSPENDED) {
101
                /// @todo decode the suspension context: date, step, ...
102
            }
103
104
            $output->writeln('Definition path: <info>' . $workflow->path . '</info>');
105
            $output->writeln('Definition md5: <info>' . $workflow->md5 . '</info>');
106
107
            if ($workflow->path != '') {
108
                // q: what if we have a loader which does not work with is_file? We could probably remove this check...
109
                if (is_file($workflow->path)) {
110
                    try {
111
                        $workflowDefinitionCollection = $workflowService->getWorkflowsDefinitions(array($workflow->path));
112
                        if (count($workflowDefinitionCollection)) {
113
                            $workflowDefinition = reset($workflowDefinitionCollection);
114
                            $workflowDefinition = $workflowService->parseWorkflowDefinition($workflowDefinition);
115
116
                            if ($workflowDefinition->status != MigrationDefinition::STATUS_PARSED) {
117
                                $output->writeln('Definition error: <error>' . $workflowDefinition->parsingError . '</error>');
118
                            }
119
120
                            if (md5($workflowDefinition->rawDefinition) != $workflow->md5) {
121
                                $output->writeln('Notes: <comment>The workflow definition file has now a different checksum</comment>');
122
                            }
123
124
                            $output->writeln('Switch User: <info>' . (($workflowDefinition->runAs === false) ? '-' : $workflowDefinition->runAs) . '</info>');
125
                            $output->writeln('Use transaction: <info>' . ($workflowDefinition->useTransaction ? 'Y' : 'N') . '</info>');
126
127
                        } else {
128
                            $output->writeln('Definition error: <error>The workflow definition file can not be loaded</error>');
129
                        }
130
                    } catch (\Exception $e) {
131
                        /// @todo one day we should be able to limit the kind of exceptions we have to catch here...
132
                        $output->writeln('Definition parsing error: <error>' . $e->getMessage() . '</error>');
133
                    }
134
                } else {
135
                    $output->writeln('Definition error: <error>The workflow definition file can not be found any more</error>');
136
                }
137
            }
138
139
            $output->writeln('');
140
            return;
141
        }
142
143
        // ask user for confirmation to make changes
144
        if ($input->isInteractive() && !$input->getOption('no-interaction')) {
145
            $dialog = $this->getHelperSet()->get('dialog');
146
            if (!$dialog->askConfirmation(
0 ignored issues
show
Bug introduced by
The method askConfirmation() does not exist on Symfony\Component\Console\Helper\Helper. It seems like you code against a sub-type of Symfony\Component\Console\Helper\Helper such as Symfony\Component\Console\Helper\DialogHelper. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

146
            if (!$dialog->/** @scrutinizer ignore-call */ askConfirmation(
Loading history...
147
                $output,
148
                '<question>Careful, the database will be modified. Do you want to continue Y/N ?</question>',
149
                false
150
            )
151
            ) {
152
                $output->writeln('<error>Workflow change cancelled!</error>');
153
                return 0;
154
            }
155
        }
156
157
        if ($input->getOption('delete')) {
158
            $workflow = $workflowService->getWorkflow($workflowNameOrPath);
159
            if ($workflow == null) {
160
                throw new \InvalidArgumentException(sprintf('The workflow "%s" does not exist in the database table.', $workflowNameOrPath));
161
            }
162
163
            $workflowService->deleteWorkflow($workflow);
164
165
            return;
166
        }
167
    }
168
}
169