Completed
Push — develop ( 7280a1...234d39 )
by Tom
04:21
created

RunCommand::executeConfigModel()   C

Complexity

Conditions 9
Paths 19

Size

Total Lines 70
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 70
rs 6.1585
cc 9
eloc 46
nc 19
nop 3

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
namespace N98\Magento\Command\System\Cron;
4
5
use Exception;
6
use Mage;
7
use Mage_Core_Model_Config_Element;
8
use Mage_Cron_Model_Schedule;
9
use RuntimeException;
10
use Symfony\Component\Console\Helper\DialogHelper;
11
use Symfony\Component\Console\Input\InputArgument;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Output\OutputInterface;
14
use Symfony\Component\Validator\Exception\InvalidArgumentException;
15
16
class RunCommand extends AbstractCronCommand
17
{
18
    const REGEX_RUN_MODEL = '#^([a-z0-9_]+/[a-z0-9_]+)::([a-z0-9_]+)$#i';
19
    /**
20
     * @var array
21
     */
22
    protected $infos;
23
24
    protected function configure()
25
    {
26
        $this
27
            ->setName('sys:cron:run')
28
            ->addArgument('job', InputArgument::OPTIONAL, 'Job code')
29
            ->setDescription('Runs a cronjob by job code');
30
        $help = <<<HELP
31
If no `job` argument is passed you can select a job from a list.
32
See it in action: http://www.youtube.com/watch?v=QkzkLgrfNaM
33
HELP;
34
        $this->setHelp($help);
35
    }
36
37
    /**
38
     * @param InputInterface $input
39
     * @param OutputInterface $output
40
     *
41
     * @return int|void
42
     */
43
    protected function execute(InputInterface $input, OutputInterface $output)
44
    {
45
        $this->detectMagento($output, true);
46
        if (!$this->initMagento()) {
47
            return;
48
        }
49
50
        $jobCode = $input->getArgument('job');
51
        if (!$jobCode) {
52
            $this->writeSection($output, 'Cronjob');
53
            $jobCode = $this->askJobCode($output, $this->getJobs());
54
        }
55
56
        $jobsRoot = Mage::getConfig()->getNode('crontab/jobs');
57
        $defaultJobsRoot = Mage::getConfig()->getNode('default/crontab/jobs');
58
59
        /* @var $jobConfig Mage_Core_Model_Config_Element */
60
        $jobConfig = $jobsRoot->{$jobCode};
61
        if (!$jobConfig || !$jobConfig->run) {
62
            $jobConfig = $defaultJobsRoot->{$jobCode};
63
        }
64
        if (!$jobConfig || !$jobConfig->run) {
65
            throw new RuntimeException(sprintf('No job-config found for job "%s"!', $jobCode));
66
        }
67
68
        /* @var $runConfig Mage_Core_Model_Config_Element */
69
        $runConfig = $jobConfig->run;
70
        if (empty($runConfig->model)) {
71
            throw new RuntimeException(sprintf('No run-config found for job "%s"!', $jobCode));
72
        }
73
74
        $this->executeConfigModel($output, (string) $runConfig->model, $jobCode);
75
    }
76
77
    /**
78
     * @param OutputInterface $output
79
     * @param array $jobs array of array containing "job" keyed string entries of job-codes
80
     *
81
     * @return string         job-code
82
     * @throws InvalidArgumentException when user selects invalid job interactively
83
     */
84
    protected function askJobCode(OutputInterface $output, array $jobs)
85
    {
86
        $index = 0;
87
        $keyMap = array_keys($jobs);
88
        $question = array();
89
90
        foreach ($jobs as $key => $job) {
91
            $question[] = '<comment>[' . ($index++) . ']</comment> ' . $job['Job'] . PHP_EOL;
92
        }
93
        $question[] = '<question>Please select job: </question>' . PHP_EOL;
94
95
        /** @var $dialogHelper DialogHelper */
96
        $dialogHelper = $this->getHelper('dialog');
97
        $jobCode = $dialogHelper->askAndValidate(
98
            $output,
99
            $question,
100
            function ($typeInput) use ($keyMap, $jobs) {
101
                $key = $keyMap[$typeInput];
102
                if (!isset($jobs[$key])) {
103
                    throw new InvalidArgumentException('Invalid job');
104
                }
105
106
                return $jobs[$key]['Job'];
107
            }
108
        );
109
110
        return $jobCode;
111
    }
112
113
    /**
114
     * @param OutputInterface $output
115
     * @param string $runConfigModel
116
     * @param $jobCode
117
     */
118
    private function executeConfigModel(
119
        OutputInterface $output,
120
        $runConfigModel,
121
        $jobCode
122
    ) {
123
        if (!preg_match(self::REGEX_RUN_MODEL, $runConfigModel, $runMatches)) {
124
            throw new RuntimeException(
125
                sprintf(
126
                    'Invalid model/method definition "%s" for job "%s", expecting "model/class::method".',
127
                    $runConfigModel,
128
                    $jobCode
129
                )
130
            );
131
        }
132
        list(, $runModel, $runMethod) = $runMatches;
133
        unset($runMatches);
134
135
        $model = Mage::getModel($runModel);
136
        if (false === $model) {
137
            throw new RuntimeException(sprintf('Failed to create new "%s" model for job "%s"', $runModel, $jobCode));
138
        }
139
        $callback = array($model, $runMethod);
140
        $callableName = sprintf("%s::%s", $runModel, $runMethod);
141
        if (!$model || !is_callable($callback, false, $callableName)) {
142
            throw new RuntimeException(sprintf('Invalid callback: %s for job "%s"', $callableName, $jobCode));
143
        }
144
145
        $output->write('<info>Run </info><comment>' . $callableName . '</comment> ');
146
147
        Mage::getConfig()->init()->loadEventObservers('crontab');
148
        Mage::app()->addEventArea('crontab');
149
150
        /* @var $schedule Mage_Cron_Model_Schedule */
151
        $schedule = Mage::getModel('cron/schedule');
152
        if (false === $schedule) {
153
            throw new RuntimeException('Failed to create new Mage_Cron_Model_Schedule model');
154
        }
155
156
        try {
157
            $timestamp = strftime('%Y-%m-%d %H:%M:%S', time());
158
            $schedule
159
                ->setJobCode($jobCode)
160
                ->setStatus(Mage_Cron_Model_Schedule::STATUS_RUNNING)
161
                ->setCreatedAt($timestamp)
162
                ->setExecutedAt($timestamp)
163
                ->save();
164
165
            call_user_func_array($callback, array($schedule));
166
167
            $schedule->setStatus(Mage_Cron_Model_Schedule::STATUS_SUCCESS);
168
        } catch (Exception $cronException) {
169
            $schedule->setStatus(Mage_Cron_Model_Schedule::STATUS_ERROR);
170
        }
171
172
        $schedule->setFinishedAt(strftime('%Y-%m-%d %H:%M:%S', time()))->save();
173
174
        if (isset($cronException)) {
175
            throw new RuntimeException(
176
                sprintf('Cron-job "%s" threw exception %s', $jobCode, get_class($cronException)),
177
                0,
178
                $cronException
179
            );
180
        }
181
182
        $output->writeln('<info>done</info>');
183
184
        if (empty($callback)) {
185
            Mage::throwException(Mage::helper('cron')->__('No callbacks found'));
186
        }
187
    }
188
}
189