Completed
Push — master ( bd5921...d9293e )
by Christian
17:54 queued 08:59
created

RunCommand::askJobCode()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 26
rs 8.8571
cc 3
eloc 16
nc 2
nop 2
1
<?php
2
3
namespace N98\Magento\Command\System\Cron;
4
5
use Exception;
6
use RuntimeException;
7
use Symfony\Component\Console\Helper\DialogHelper;
8
use Symfony\Component\Console\Input\InputArgument;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\Validator\Exception\InvalidArgumentException;
12
13
class RunCommand extends AbstractCronCommand
14
{
15
    const REGEX_RUN_MODEL = '#^([a-z0-9_]+/[a-z0-9_]+)::([a-z0-9_]+)$#i';
16
    /**
17
     * @var array
18
     */
19
    protected $infos;
20
21
    protected function configure()
22
    {
23
        $this
24
            ->setName('sys:cron:run')
25
            ->addArgument('job', InputArgument::OPTIONAL, 'Job code')
26
            ->setDescription('Runs a cronjob by job code');
27
        $help = <<<HELP
28
If no `job` argument is passed you can select a job from a list.
29
See it in action: http://www.youtube.com/watch?v=QkzkLgrfNaM
30
HELP;
31
        $this->setHelp($help);
32
    }
33
34
    /**
35
     * @param InputInterface $input
36
     * @param OutputInterface $output
37
     *
38
     * @return int|void
39
     */
40
    protected function execute(InputInterface $input, OutputInterface $output)
41
    {
42
        $this->detectMagento($output, true);
43
        if ($this->initMagento()) {
44
45
            $jobCode = $input->getArgument('job');
46
            if (!$jobCode) {
47
                $this->writeSection($output, 'Cronjob');
48
                $jobCode = $this->askJobCode($output, $this->getJobs());
49
            }
50
51
            $jobsRoot = \Mage::getConfig()->getNode('crontab/jobs');
52
            $defaultJobsRoot = \Mage::getConfig()->getNode('default/crontab/jobs');
53
54
            $jobConfig = $jobsRoot->{$jobCode};
55
            if (!$jobConfig || !$jobConfig->run) {
56
                $jobConfig = $defaultJobsRoot->{$jobCode};
57
                if (!$jobConfig || !$jobConfig->run) {
58
                    throw new RuntimeException('No job config found!');
59
                }
60
            }
61
62
            $runConfig = $jobConfig->run;
63
64
            if ($runConfig->model) {
65
66
                if (!preg_match(self::REGEX_RUN_MODEL, (string) $runConfig->model, $run)) {
67
                    throw new RuntimeException('Invalid model/method definition, expecting "model/class::method".');
68
                }
69
                if (!($model = \Mage::getModel($run[1])) || !method_exists($model, $run[2])) {
70
                    throw new RuntimeException(sprintf('Invalid callback: %s::%s does not exist', $run[1], $run[2]));
71
                }
72
                $callback = array($model, $run[2]);
73
74
                $output->write('<info>Run </info><comment>' . get_class($model) . '::' . $run[2] . '</comment> ');
75
76
                try {
77
                    $schedule = \Mage::getModel('cron/schedule');
78
                    $schedule
79
                        ->setJobCode($jobCode)
80
                        ->setStatus(\Mage_Cron_Model_Schedule::STATUS_RUNNING)
81
                        ->setExecutedAt(strftime('%Y-%m-%d %H:%M:%S', time()))
82
                        ->save();
83
84
                    call_user_func_array($callback, array($schedule));
85
86
                    $schedule
87
                        ->setStatus(\Mage_Cron_Model_Schedule::STATUS_SUCCESS)
88
                        ->setFinishedAt(strftime('%Y-%m-%d %H:%M:%S', time()))
89
                        ->save();
90
                } catch (Exception $e) {
91
                    $schedule
92
                        ->setStatus(\Mage_Cron_Model_Schedule::STATUS_ERROR)
93
                        ->setMessages($e->getMessage())
94
                        ->setFinishedAt(strftime('%Y-%m-%d %H:%M:%S', time()))
95
                        ->save();
96
                }
97
98
                $output->writeln('<info>done</info>');
99
            }
100
            if (empty($callback)) {
101
                \Mage::throwException(Mage::helper('cron')->__('No callbacks found'));
102
            }
103
        }
104
    }
105
106
    /**
107
     * @param OutputInterface $output
108
     * @param array           $jobs array of array containing "job" keyed string entries of job-codes
109
     *
110
     * @return string         job-code
111
     * @throws InvalidArgumentException when user selects invalid job interactively
112
     */
113
    protected function askJobCode(OutputInterface $output, array $jobs)
114
    {
115
        $index = 0;
116
        $keyMap = array_keys($jobs);
117
118
        foreach ($jobs as $key => $job) {
119
            $question[] = '<comment>[' . ($index++) . ']</comment> ' . $job['Job'] . PHP_EOL;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$question was never initialized. Although not strictly required by PHP, it is generally a good practice to add $question = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
120
        }
121
        $question[] = '<question>Please select job: </question>' . PHP_EOL;
0 ignored issues
show
Bug introduced by
The variable $question does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
122
123
        /** @var $dialogHelper DialogHelper */
124
        $dialogHelper = $this->getHelperSet()->get('dialog');
125
        $jobCode = $dialogHelper->askAndValidate(
126
            $output,
127
            $question,
128
            function($typeInput) use ($keyMap, $jobs) {
129
                $key = $keyMap[$typeInput];
130
                if (!isset($jobs[$key])) {
131
                    throw new InvalidArgumentException('Invalid job');
132
                }
133
                return $jobs[$key]['Job'];
134
            }
135
        );
136
137
        return $jobCode;
138
    }
139
}
140