Файл: concrete5.7.5.6/concrete/src/Job/Job.php
Строк: 393
<?php
namespace ConcreteCoreJob;
use ConcreteCoreFoundationObject;
use Loader;
use ConcreteCorePackagePackageList;
use Config;
use Core;
use Events;
use stdClass;
abstract class Job extends Object
{
const JOB_SUCCESS = 0;
const JOB_ERROR_EXCEPTION_GENERAL = 1;
abstract public function run();
abstract public function getJobName();
abstract public function getJobDescription();
public function getJobHandle() {return $this->jHandle;}
public function getJobID() {return $this->jID;}
public function getPackageHandle()
{
return PackageList::getHandle($this->pkgID);
}
public function getJobLastStatusCode()
{
return $this->jLastStatusCode;
}
public function didFail()
{
return in_array($this->jLastStatusCode, array(
static::JOB_ERROR_EXCEPTION_GENERAL
));
}
public function canUninstall()
{
return $this->jNotUninstallable != 1;
}
public function supportsQueue() {return ($this instanceof QueueableJob);}
//==========================================================
// JOB MANAGEMENT - do not override anything below this line
//==========================================================
//meta variables
protected $jobClassLocations=array();
//Other Job Variables
public $jID=0;
public $jStatus='ENABLED';
public $availableJStatus=array( 'ENABLED','RUNNING','ERROR','DISABLED_ERROR','DISABLED' );
public $jDateLastRun;
public $jHandle='';
public $jNotUninstallable=0;
public $isScheduled = 0;
public $scheduledInterval = 'days'; // hours|days|weeks|months
public $scheduledValue = 0;
/*
final public __construct(){
//$this->jHandle="example_job_file.php";
}
*/
public static function jobClassLocations()
{
return array(DIR_FILES_JOBS, DIR_FILES_JOBS_CORE);
}
public function getJobDateLastRun() {return $this->jDateLastRun;}
public function getJobStatus() {return $this->jStatus;}
public function getJobLastStatusText() {return $this->jLastStatusText;}
// authenticateRequest checks against your site's job security token and a custom auth field to make
// sure that this is a request that is coming either from something cronned by the site owner
// or from the dashboard
public static function authenticateRequest($auth)
{
// this is a little tricky. We have TWO ways of doing this
// 1. Does the security token for jobs md5 correctly? If so, good.
$val = Core::make('config/database')->get('concrete.security.token.jobs') . ':' . DIRNAME_JOBS;
if (md5($val) == $auth) {
return true;
}
}
public static function generateAuth()
{
$val = Core::make('config/database')->get('concrete.security.token.jobs') . ':' . DIRNAME_JOBS;
return md5($val);
}
public static function exportList($xml)
{
$jobs = static::getList();
if (count($jobs) > 0) {
$jx = $xml->addChild('jobs');
foreach ($jobs as $j) {
$ch = $jx->addChild('job');
$ch->addAttribute('handle',$j->getJobHandle());
$ch->addAttribute('package',$j->getPackageHandle());
}
}
}
// Job Retrieval
// ==============
/**
* @param bool $scheduledOnly
* @return Job[]
*/
public static function getList($scheduledOnly = false)
{
$db = Loader::db();
if ($scheduledOnly) {
$q = "SELECT jID FROM Jobs WHERE isScheduled = 1 ORDER BY jDateLastRun, jID";
} else {
$q = "SELECT jID FROM Jobs ORDER BY jDateLastRun, jID";
}
$r = $db->Execute($q);
$jobs = array();
while ($row = $r->FetchRow()) {
$j = static::getByID($row['jID']);
if (is_object($j)) {
$jobs[] = $j;
}
}
return $jobs;
}
public function reset()
{
$db = Loader::db();
$db->Execute('update Jobs set jLastStatusCode = 0, jStatus = 'ENABLED' where jID = ?', array($this->jID));
}
public function markStarted()
{
$je = new Event($this);
Events::dispatch('on_before_job_execute', $je);
$db = Loader::db();
$timestampH =date('Y-m-d g:i:s A');
$timestamp=date('Y-m-d H:i:s');
$this->jDateLastRun = $timestampH;
$rs = $db->query( "UPDATE Jobs SET jStatus='RUNNING', jDateLastRun=? WHERE jHandle=?", array( $timestamp, $this->jHandle ) );
}
public function markCompleted($resultCode = 0, $resultMsg = false)
{
$db = Loader::db();
if (!$resultMsg) {
$resultMsg= t('The Job was run successfully.');
}
if (!$resultCode) {
$resultCode = 0;
}
$jStatus='ENABLED';
if ($this->didFail()) {
$jStatus = 'ERROR';
}
$timestamp=date('Y-m-d H:i:s');
$rs = $db->query( "UPDATE Jobs SET jStatus=?, jLastStatusCode = ?, jLastStatusText=? WHERE jHandle=?", array( $jStatus, $resultCode, $resultMsg, $this->jHandle ) );
$rs = $db->query( "INSERT INTO JobsLog (jID, jlMessage, jlTimestamp, jlError) VALUES(?,?,?,?)", array( $this->jID, $resultMsg, $timestamp, $resultCode ) );
$je = new Event($this);
Events::dispatch('on_job_execute', $je);
$obj = new JobResult();
$obj->error = $resultCode;
$obj->result = $resultMsg;
$obj->jDateLastRun = Core::make('helper/date')->formatDateTime('now', true, true);
$obj->jHandle = $this->getJobHandle();
$obj->jID = $this->getJobID();
$this->jLastStatusCode = $resultCode;
$this->jLastStatusText = $resultMsg;
$this->jStatus = $jStatus;
return $obj;
}
public static function getByID($jID=0)
{
$db = Loader::db();
$jobData = $db->getRow("SELECT * FROM Jobs WHERE jID=".intval($jID));
if( !$jobData || !$jobData['jHandle'] ) return NULL;
return static::getJobObjByHandle( $jobData['jHandle'], $jobData );
}
public static function getByHandle($jHandle='')
{
$db = Loader::db();
$jobData = $db->getRow( 'SELECT * FROM Jobs WHERE jHandle=?', array($jHandle) );
if( !$jobData || !$jobData['jHandle'] ) return NULL;
return static::getJobObjByHandle( $jobData['jHandle'], $jobData );
}
public static function getJobObjByHandle( $jHandle='', $jobData=array() )
{
$jcl = static::jobClassLocations();
$pkgHandle = null;
//check for the job file in the various locations
$db = Loader::db();
$pkgID = $db->GetOne('select pkgID from Jobs where jHandle = ?', $jHandle);
if ($pkgID > 0) {
$pkgHandle = PackageList::getHandle($pkgID);
if ($pkgHandle) {
$jcl[] = DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_JOBS;
$jcl[] = DIR_PACKAGES_CORE . '/' . $pkgHandle . '/' . DIRNAME_JOBS;
}
}
foreach ($jcl as $jobClassLocation) {
//load the file & class, then run the job
$path=$jobClassLocation.'/'.$jHandle.'.php';
if ( file_exists($path) ) {
$className = static::getClassName($jHandle, $pkgHandle);
$j = Core::make($className);
$j->jHandle=$jHandle;
if (intval($jobData['jID'])>0) {
$j->setPropertiesFromArray($jobData);
}
return $j;
}
}
return NULL;
}
protected static function getClassName($jHandle, $pkgHandle = null)
{
$class = overrideable_core_class('Job\' . camelcase($jHandle), DIRNAME_JOBS . '/' . $jHandle . '.php', $pkgHandle);
return $class;
}
//Scan job directories for job classes
public static function getAvailableList($includeConcreteDirJobs=1)
{
$jobObjs=array();
//get existing jobs
$existingJobHandles=array();
$existingJobs = static::getList();
foreach ($existingJobs as $j) {
$existingJobHandles[] = $j->getJobHandle();
}
if(!$includeConcreteDirJobs)
$jobClassLocations = array( DIR_FILES_JOBS );
else $jobClassLocations = static::jobClassLocations();
foreach ($jobClassLocations as $jobClassLocation) {
// Open a known directory, and proceed to read its contents
if (is_dir($jobClassLocation)) {
if ($dh = opendir($jobClassLocation)) {
while (($file = readdir($dh)) !== false) {
if( substr($file,strlen($file)-4)!='.php' ) continue;
$alreadyInstalled=0;
foreach ($existingJobHandles as $existingJobHandle) {
if ( substr($file,0,strlen($file)-4)==$existingJobHandle) {
$alreadyInstalled=1;
break;
}
}
if($alreadyInstalled) continue;
$jHandle = substr($file,0,strlen($file)-4);
$className = static::getClassName($jHandle);
$jobObjs[$jHandle] = Core::make($className);
$jobObjs[$jHandle]->jHandle = $jHandle;
}
closedir($dh);
}
}
}
return $jobObjs;
}
// Running Jobs
// ==============
/*
public static function runAllJobs()
{
//loop through all installed jobs
$jobs = Job::getList();
foreach ($jobs as $j) {
$j->executeJob();
}
}
*/
public function executeJob()
{
$this->markStarted();
try {
$resultMsg=$this->run();
if (strlen($resultMsg)==0) {
$resultMsg= t('The Job was run successfully.');
}
} catch (Exception $e) {
$resultMsg=$e->getMessage();
$error = static::JOB_ERROR_EXCEPTION_GENERAL;
}
$je = new Event($this);
Events::dispatch('on_job_execute', $je);
$obj = $this->markCompleted($error, $resultMsg);
return $obj;
}
public function setJobStatus($jStatus='ENABLED')
{
$db = Loader::db();
if( !in_array($jStatus,$this->availableJStatus) )
$jStatus='ENABLED';
$rs = $db->query( "UPDATE Jobs SET jStatus=? WHERE jHandle=?", array( $jStatus, $this->jHandle ) );
}
public static function installByHandle($jHandle='')
{
$availableJobs=static::getAvailableList();
foreach ($availableJobs as $availableJobHandle=>$availableJobObj) {
if( $availableJobHandle!=$jHandle ) continue;
$availableJobObj->install();
}
}
public static function getListByPackage($pkg)
{
$db = Loader::db();
$list = array();
$r = $db->Execute('select jHandle from Jobs where pkgID = ? order by jHandle asc', array($pkg->getPackageID()));
while ($row = $r->FetchRow()) {
$list[] = static::getJobObjByHandle($row['jHandle']);
}
$r->Close();
return $list;
}
public static function installByPackage($jHandle, $pkg)
{
$className = static::getClassName($jHandle, $pkg->getPackageHandle());
if (class_exists($className)) {
$j = Core::make($className);
$db = Loader::db();
$db->Execute('insert into Jobs (jName, jDescription, jDateInstalled, jNotUninstallable, jHandle, pkgID) values (?, ?, ?, ?, ?, ?)',
array($j->getJobName(), $j->getJobDescription(), Loader::helper('date')->getOverridableNow(), 0, $jHandle, $pkg->getPackageID()));
$je = new Event($j);
Events::dispatch('on_job_install', $je);
$j->jID = $db->Insert_ID();
return $j;
}
}
public function install()
{
$db = Loader::db();
$jobExists=$db->getOne( 'SELECT count(*) FROM Jobs WHERE jHandle=?', array($this->jHandle) );
$vals=array($this->getJobName(),$this->getJobDescription(), date('Y-m-d H:i:s'), $this->jNotUninstallable, $this->jHandle);
if ($jobExists) {
$db->query('UPDATE Jobs SET jName=?, jDescription=?, jDateInstalled=?, jNotUninstallable=? WHERE jHandle=?',$vals);
} else {
$db->query('INSERT INTO Jobs (jName, jDescription, jDateInstalled, jNotUninstallable, jHandle) VALUES(?,?,?,?,?)',$vals);
}
$je = new Event($this);
Events::dispatch('on_job_install', $je);
}
public function uninstall()
{
$je = new Event($this);
$je = Events::dispatch('on_job_uninstall', $je);
if (!$je) {
return false;
}
$db = Loader::db();
$db->query( 'DELETE FROM Jobs WHERE jHandle=?', array($this->jHandle) );
}
/**
* Removes Job log entries
*/
public static function clearLog()
{
$db = Loader::db();
$db->Execute("delete from JobsLog");
}
public function isScheduledForNow()
{
if (!$this->isScheduled) {
return false;
}
if ($this->scheduledValue <= 0) {
return false;
}
$last_run = strtotime($this->jDateLastRun);
$seconds = 1;
switch ($this->scheduledInterval) {
case "minutes":
$seconds = 60;
break;
case "hours":
$seconds = 60*60;
break;
case "days":
$seconds = 60*60*24;
break;
case "weeks":
$seconds = 60*60*24*7;
break;
case "months":
$seconds = 60*60*24*7*30;
break;
}
$gap = $this->scheduledValue * $seconds;
if ($last_run < (time() - $gap) ) {
return true;
} else {
return false;
}
}
public function setSchedule($scheduled, $interval, $value)
{
$this->isScheduled = $scheduled ? 1 : 0;
$this->scheduledInterval = Loader::helper('security')->sanitizeString($interval);
$this->scheduledValue = $value;
if ($this->getJobID()) {
$db = Loader::db();
$db->query("UPDATE Jobs SET isScheduled = ?, scheduledInterval = ?, scheduledValue = ? WHERE jID = ?",
array($this->isScheduled, $this->scheduledInterval, $this->scheduledValue, $this->getJobID()));
return true;
} else {
return false;
}
}
}