1:  2:  3:  4:  5:  6:  7:  8:  9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 
<?php
namespace Omeka\Job\DispatchStrategy;

use DateTime;
use Doctrine\ORM\EntityManager;
use Omeka\Entity\Job;
use Zend\ServiceManager\ServiceLocatorInterface;

class Synchronous implements StrategyInterface
{
    /**
     * @var ServiceLocatorInterface
     */
    protected $serviceLocator;

    /**
     * @param ServiceLocatorInterface $serviceLocator
     */
    public function __construct(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
    }

    /**
     * {@inheritDoc}
     */
    public function send(Job $job)
    {
        $entityManager = $this->serviceLocator->get('Omeka\EntityManager');
        register_shutdown_function([$this, 'handleFatalError'], $job, $entityManager);

        $job->setStatus(Job::STATUS_IN_PROGRESS);
        $entityManager->flush();

        $class = $job->getClass();
        $jobClass = new $class($job, $this->serviceLocator);
        $jobClass->perform();

        if (Job::STATUS_STOPPING == $job->getStatus()) {
            $job->setStatus(Job::STATUS_STOPPED);
        } else {
            $job->setStatus(Job::STATUS_COMPLETED);
        }
        $job->setEnded(new DateTime('now'));
        $entityManager->clear();
        $entityManager->merge($job);
        $entityManager->flush();
    }

    /**
     * Log status and message if job terminates with a fatal error
     *
     * @param Job $job
     * @param EntityManager $entityManager
     */
    public function handleFatalError(Job $job, EntityManager $entityManager)
    {
        $lastError = error_get_last();
        $errors = [E_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR];
        if ($lastError && in_array($lastError['type'], $errors)) {
            $job->setStatus(Job::STATUS_ERROR);
            $job->addLog(sprintf("Fatal error: %s\nin %s on line %s",
                $lastError['message'],
                $lastError['file'],
                $lastError['line']
            ));

            // Make sure we only flush this Job and nothing else
            $entityManager->clear();
            $entityManager->merge($job);
            $entityManager->flush();
        }
    }
}