Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added sys:cron:schedule command #257

Merged
merged 9 commits into from Dec 31, 2016
1 change: 1 addition & 0 deletions config.yaml
Expand Up @@ -90,6 +90,7 @@ commands:
- N98\Magento\Command\System\Cron\HistoryCommand
- N98\Magento\Command\System\Cron\ListCommand
- N98\Magento\Command\System\Cron\RunCommand
- N98\Magento\Command\System\Cron\ScheduleCommand
- N98\Magento\Command\System\InfoCommand
- N98\Magento\Command\System\MaintenanceCommand
- N98\Magento\Command\System\Setup\ChangeVersionCommand
Expand Down
8 changes: 8 additions & 0 deletions src/N98/Magento/Command/System/Cron/AbstractCronCommand.php
Expand Up @@ -31,17 +31,24 @@ abstract class AbstractCronCommand extends AbstractMagentoCommand
*/
protected $_cronScheduleCollection;

/**
* @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
*/
protected $_timezone;

/**
* @param \Magento\Framework\App\State $state
* @param \Magento\Framework\Event\ManagerInterface $eventManager
* @param \Magento\Cron\Model\ConfigInterface $cronConfig
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* @param \Magento\Cron\Model\ResourceModel\Schedule\Collection $cronScheduleCollection
*/
public function inject(
\Magento\Framework\App\State $state,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Cron\Model\ConfigInterface $cronConfig,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Cron\Model\ResourceModel\Schedule\Collection $cronScheduleCollection
) {
Expand All @@ -50,6 +57,7 @@ public function inject(
$this->_cronConfig = $cronConfig;
$this->_scopeConfig = $scopeConfig;
$this->_cronScheduleCollection = $cronScheduleCollection;
$this->_timezone = $timezone;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please convert ->... properties to ones w/o "" at the beginning. I know it's now all your code, so please at least do it for new introduced properties even if code-style changes that way (it changes to the correct way).

}

/**
Expand Down
107 changes: 107 additions & 0 deletions src/N98/Magento/Command/System/Cron/ScheduleCommand.php
@@ -0,0 +1,107 @@
<?php

namespace N98\Magento\Command\System\Cron;

use Magento\Cron\Model\Schedule;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class ScheduleCommand extends AbstractCronCommand
{
protected function configure()
{
$this
->setName('sys:cron:schedule')
->addArgument('job', InputArgument::OPTIONAL, 'Job code')
->setDescription('Schedule a cronjob for execution right now, by job code');
$help = <<<HELP
If no `job` argument is passed you can select a job from a list.
HELP;
$this->setHelp($help);
}

/**
* @param InputInterface $input
* @param OutputInterface $output
* @throws \Exception
* @return int|void
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$jobCode = $input->getArgument('job');
$jobs = $this->getJobs();

if (!$jobCode) {
$this->writeSection($output, 'Cronjob');
$jobCode = $this->askJobCode($input, $output, $jobs);
}

$jobConfig = $this->getJobConfig($jobCode);

if (empty($jobCode) || !isset($jobConfig['instance'])) {
throw new \InvalidArgumentException('No job config found!');
}

$model = $this->getObjectManager()->get($jobConfig['instance']);

if (!$model || !is_callable(array($model, $jobConfig['method']))) {
throw new \RuntimeException(
sprintf(
'Invalid callback: %s::%s does not exist',
$jobConfig['instance'],
$jobConfig['method']
)
);
}

$output->write(
'<info>Scheduling </info><comment>' . $jobConfig['instance'] . '::' . $jobConfig['method'] . '</comment> '
);

// add one second from the current time, just because it feels better ...
$scheduledAtTime = $this->_timezone->scopeTimeStamp() + 1;

$schedule = $this->_cronScheduleCollection->getNewEmptyItem();
$schedule
->setJobCode($jobCode)
->setStatus(Schedule::STATUS_PENDING)
->setCreatedAt(strftime('%Y-%m-%d %H:%M:%S', $this->_timezone->scopeTimeStamp()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created at with seconds, good.

->setScheduledAt($scheduledAtTime)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be a formatted timestamp as well, correct me if not.

->save();

$output->writeln('<info>done</info>');
}

/**
* @param InputInterface $input
* @param OutputInterface $output
* @param array $jobs
* @return string
* @throws \InvalidArgumentException
* @throws \Exception
*/
protected function askJobCode(InputInterface $input, OutputInterface $output, $jobs)
{
foreach ($jobs as $key => $job) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly we don't offer anything less cumbersome here. This might be something worth in a base-class if shared with the other command as asking is command related (less cron sheduling related, at least for most of this code).

$question[] = '<comment>[' . ($key + 1) . ']</comment> ' . $job['Job'] . PHP_EOL;
}
$question[] = '<question>Please select job: </question>' . PHP_EOL;

/** @var $dialog DialogHelper */
$dialog = $this->getHelper('dialog');
$jobCode = $dialog->askAndValidate(
$output,
$question,
function ($typeInput) use ($jobs) {
if (!isset($jobs[$typeInput - 1])) {
throw new \InvalidArgumentException('Invalid job');
}
return $jobs[$typeInput - 1]['Job'];
}
);

return $jobCode;
}
}