* @since Version 1.0 * * Writes the $_SESSION content to disk and relinquishes the lock. * After starting a new process automatically locks session - writing to $_SESSION will result in loss of data */ class cProcess { public $oApc; private $sProcessId; private $bUseSession; private $bSessionClosed = false; const PROCESS_SESSION_KEY = 'session_processes'; const PROCESS_STATUS_ACTIVE = 'active'; const PROCESS_STATUS_ABORTED = 'aborted'; const PROCESS_STATUS_EXPIRED = 'expired'; const PROCESS_STATUS_FINISHED = 'finished'; const KEY_PROGRESS = 'progress'; const KEY_PROGRESS_MSG = 'progressMsg'; const KEY_PROGRESS_STATUS = 'processStatus'; private $iProgressStep = 0; private $iCurrentProgressVal = 0; /** * Class constructor * @param string|boolean $sProcessId - passed process id * @param boolean $bStartProcess - start new process by the given id * @param boolean $bUseSession - use session as data conduit * @param cApc|boolean $oApc - cache APC object */ public function __construct($sProcessId = false, $bStartProcess = true, $bUseSession = true, &$oApc = false){ $this->oApc = $oApc; $this->sProcessId = $sProcessId; $this->bUseSession = $bUseSession; if($sProcessId && $bStartProcess) $this->startProcess($sProcessId); } /** * Function to relinquish session for other process request to use * * @author Mareks Keišs * @category pubDocuments Controller * * @return void */ public function closeSession(){ if($this->bUseSession && !$this->bSessionClosed){ // Writes the $_SESSION content to disk and relinquishes the lock. // After this writing to $_SESSION will result in loss of data session_write_close(); $this->bSessionClosed = true; } } /** * Function to restart session for this process request to use * * @author Mareks Keišs * @category pubDocuments Controller * * @return void */ public function restartSession(){ if($this->bUseSession && $this->bSessionClosed){ unset($_SESSION); startSessionSameSite(60*60*24); $this->bSessionClosed = false; } } /** * Function to start new process * * @author Mareks Keišs * @category pubDocuments Controller * @param string $sProcessId - process id * @param array $vData * @param int $iTTL - tile to live by default 60*20 * @return bool */ public function startProcess($sProcessId, $vData = array(), $iTTL = 1200){ $vSaveData = array( 'startTime' => date('d.m.Y H:i:s'), 'startTimeUnix' => time(), self::KEY_PROGRESS => 0, self::KEY_PROGRESS_MSG => '', self::KEY_PROGRESS_STATUS => self::PROCESS_STATUS_ACTIVE, 'ttl' => $iTTL, ); // Add additional data if(!!$vData) $vSaveData = $vData + $vSaveData; if($this->bUseSession){ $_SESSION[self::PROCESS_SESSION_KEY][$sProcessId] = $vSaveData; $this->closeSession(); }else $this->oApc->store("P_{$sProcessId}", $vSaveData, $iTTL); return true; } /** * Function to start update process * * @author Mareks Keišs * @category pubDocuments Controller * @param string|boolean $sProcessId - process id * @param array $vData * @param int $iTTL - tile to live by default 60*20 * @return bool */ public function updateProcess($sProcessId = false, $vData, $iTTL = 1200){ $sProcessId = ($sProcessId ? $sProcessId : $this->sProcessId); if(!!$vData){ if($this->bUseSession){ $this->restartSession(); if(isset($_SESSION[self::PROCESS_SESSION_KEY][$sProcessId])){ $_SESSION[self::PROCESS_SESSION_KEY][$sProcessId] = $vData + $_SESSION[self::PROCESS_SESSION_KEY][$sProcessId]; } $this->closeSession(); return true; }else{ if($this->oApc->exists("P_{$sProcessId}") && !!$vData){ $vProcessData = $this->oApc->check("P_{$sProcessId}"); $vProcessData = $vData + $vProcessData; $this->oApc->store("P_{$sProcessId}", $vProcessData, $iTTL); return true; } } } return false; } /** * Function to get process data * * @author Mareks Keišs * @category pubDocuments Controller * @param string|boolean $sProcessId - process id * @return mixed */ public function getProcess($sProcessId = false){ $sProcessId = ($sProcessId ? $sProcessId : $this->sProcessId); if($this->bUseSession){ $this->restartSession(); if(isset($_SESSION[self::PROCESS_SESSION_KEY][$sProcessId])){ $this->closeSession(); return $_SESSION[self::PROCESS_SESSION_KEY][$sProcessId]; } }else{ if($this->oApc->exists("P_{$sProcessId}")){ return $this->oApc->check("P_{$sProcessId}"); } } return false; } /** * Function to abort process * * @author Mareks Keišs * @category pubDocuments Controller * @param string|boolean $sProcessId - process id * @return mixed */ public function abortProcess($sProcessId = false){ return $this->updateProcess(array('processStatus' => self::PROCESS_STATUS_ABORTED), $sProcessId); } /** * Function to destroy process * * @author Mareks Keišs * @category pubDocuments Controller * @param string|boolean $sProcessId - process id * @return mixed */ public function destroyProcess($sProcessId = false){ $sProcessId = ($sProcessId ? $sProcessId : $this->sProcessId); if($this->bUseSession){ $this->restartSession(); unset($_SESSION[self::PROCESS_SESSION_KEY][$sProcessId]); $this->closeSession(); }else $this->oApc->setExpired("P_{$sProcessId}"); return true; } /** * Function to check if process aborted process * * @author Mareks Keišs * @category pubDocuments Controller * @param string|boolean $sProcessId - process id * @return mixed */ public function chkProcessAbortStatus($sProcessId = false){ $vProcess = $this->getProcess($sProcessId); if($vProcess && !empty($vProcess['processStatus']) && $vProcess['processStatus'] == self::PROCESS_STATUS_ABORTED) return true; return false; } /** * Function to update process progress value & msg * * @author Mareks Keišs * @category pubDocuments Controller * @param int|boolean $iPercent - process percent progress * @param string|boolean $sMsg - process progress message * @param string|boolean $sProcessId - process id * @return mixed */ public function updProcessProgress($iPercent = false, $sMsg = false, $sProcessId = false){ $vUpdateData = array(); if(!!$iPercent) $vUpdateData[self::KEY_PROGRESS] = number_format($iPercent); if(!!$sMsg) $vUpdateData[self::KEY_PROGRESS_MSG] = $sMsg; if(!!$vUpdateData)$this->updateProcess($sProcessId, $vUpdateData); return false; } /** * Convenience Function to calculate & set progress step based upon passed iteration count * * @author Mareks Keišs * @category pubDocuments Controller * @param int|boolean $iIterations - iterations to 100% * @param int $iMaxPercentagePerStep - maximum allowed percentage * @return void */ public function setProcessProgressStep($iIterations = false, $iMaxPercentagePerStep = 100){ if(!!$iIterations){ if($iMaxPercentagePerStep < 0 || $iMaxPercentagePerStep > 100) $iMaxPercentagePerStep = 100; $this->iProgressStep = $iMaxPercentagePerStep / $iIterations; $this->iCurrentProgressVal = 0; } } /** * Convenience Function to calculate & update progress based upon next step * * @author Mareks Keišs * @category pubDocuments Controller * @param string|boolean $sMsg - process progress message * @return void */ public function updProcessProgressByStep($sMsg = false){ if(!!$this->iProgressStep){ $this->iCurrentProgressVal += $this->iProgressStep; if($this->iCurrentProgressVal > 100) $this->iCurrentProgressVal = 100; } $this->updProcessProgress($this->iCurrentProgressVal, $sMsg); } }