self::MODE_PREVIZ, 'blog'=>self::MODE_BLOG, 'histo'=>self::MODE_HISTO]; //DB Tables public const PROJ_TABLE = 'projects'; /** * Database Handle * @var Db */ private $oDb; private $iProjectId; private $sName; private $sCodeName; private $sMode; private $asActive; public function __construct(Db &$oDb, $iProjectId=0) { parent::__construct(__CLASS__); $this->oDb = &$oDb; if($iProjectId > 0) $this->setProjectId($iProjectId); } public function getProjectId() { return $this->iProjectId; } public function setProjectId($iProjectId=0) { if($iProjectId > 0) { $this->iProjectId = $iProjectId; } else { /** * Project 1 [-----------------] * Project 2 [---------------------------] * Project 3 [-----------] * Selected Project [-------Project 1-------][------------Project 2-------------][---------------Project 3------------------ * Mode --P--][--------B--------][--P--][-----------B---------------][---P---][-----B-----][---------H---------- */ $sQuery = 'SELECT MAX(id_project) '. 'FROM projects '. 'WHERE active_to = ('. 'SELECT MIN(active_to) '. //Select closest project in the future 'FROM projects '. 'WHERE active_to > NOW() '. //Select Next project 'OR active_to = ('. //In case there is no next project, select the last one 'SELECT MAX(active_to) '. 'FROM projects'. ')'. ')'; $asResult = $this->oDb->getArrayQuery($sQuery, true); $this->iProjectId = array_shift($asResult); } $this->setProjectInfo(); } public function createProjectId() { $this->setProjectId($this->oDb->insertRow(self::PROJ_TABLE, ['codename'=>''])); return $this->getProjectId(); } public function getMode() { return $this->sMode; } public function getProjectName() { return $this->sName; } public function setProjectName($sName) { return $this->updateField('name', $sName); } public function getProjectCodeName() { return $this->sCodeName; } public function setProjectCodeName($sCodeName) { return $this->updateField('codename', $sCodeName); } public function getActivePeriod($sFromTo='') { return ($sFromTo=='')?$this->asActive:$this->asActive[$sFromTo]; } public function setActivePeriod($oValue, $sFromTo='') { if($sFromTo=='') { $this->updateField('active_from', $oValue['from']); return $this->updateField('active_to', $oValue['to']); } else { return $this->updateField('active_'.$sFromTo, $oValue); } } public function getFeedIds() { return $this->oDb->selectColumn( Feed::FEED_TABLE, Db::getId(Feed::FEED_TABLE), [Db::getId(self::PROJ_TABLE) => $this->getProjectId()] ); } public function getProjects($iProjectId=0) { $bSpecificProj = ($iProjectId > 0); $sDefaultProjectCodeName = $this->getProjectCodeName(); $asInfo = [ 'select'=> [ Db::getId(self::PROJ_TABLE).' AS id', 'codename', 'name', 'latitude', 'longitude', 'active_from', 'active_to', 'IF(NOW() BETWEEN active_from AND active_to, 1, IF(NOW() < active_from, 0, 2)) AS mode' ], 'from' => self::PROJ_TABLE, 'orderBy' => ['active_from' => 'ASC'] ]; if($bSpecificProj) $asInfo['constraint'] = [Db::getId(self::PROJ_TABLE)=>$iProjectId]; $asProjects = $this->oDb->selectRows($asInfo, 'codename'); foreach($asProjects as $sCodeName => &$asProject) { //Update geoJSON if(Converter::hasGpxFile($sCodeName) && (!Converter::isGeoJsonValid($sCodeName) || !$asProject['latitude'] && !$asProject['longitude'])) { $aiCenter = Converter::convertToGeoJson($sCodeName)['center']; $this->oDb->updateRow(self::PROJ_TABLE, $asProject['id'], ['latitude' => $aiCenter[1], 'longitude' => $aiCenter[0]]); $asProject['latitude'] = $aiCenter[1]; $asProject['longitude'] = $aiCenter[0]; } switch($asProject['mode']) { case 0: $asProject['mode'] = self::MODE_PREVIZ; break; case 1: $asProject['mode'] = self::MODE_BLOG; break; case 2: $asProject['mode'] = self::MODE_HISTO; break; } $asProject['editable'] = $this->isModeEditable($asProject['mode']); $asProject['gpxfilepath'] = Livetrail::addTimestampToFilePath(Gpx::getFrontendFilePath($sCodeName)); $asProject['geofilepath'] = Livetrail::addTimestampToFilePath(GeoJson::getFrontendFilePath($sCodeName)); $asProject['codename'] = $sCodeName; $asProject['default'] = ($sCodeName == $sDefaultProjectCodeName); } return $bSpecificProj?$asProject:$asProjects; } public function getProject() { return $this->getProjects($this->getProjectId()); } public function getLastUpdate(): int { $iLastUpdate = INF; $asFeedIds = $this->getFeedIds(); foreach($asFeedIds as $iFeedId) { $iLastUpdate = min($iLastUpdate, (new Feed($this->oDb, $iFeedId))->getLastUpdate()); } return $iLastUpdate; } public function getLastMessageId($asConstraints=[]): int { $iLastMsg = 0; $asFeedIds = $this->getFeedIds(); foreach($asFeedIds as $iFeedId) { $iLastMsg = max($iLastMsg, (new Feed($this->oDb, $iFeedId))->getLastMessageId($asConstraints)); } return $iLastMsg; } private function setProjectInfo() { if($this->getProjectId() > 0) { $asProject = $this->getProject(); $this->sName = $asProject['name']; $this->sCodeName = $asProject['codename']; $this->sMode = $asProject['mode']; $this->asActive = ['from'=>$asProject['active_from'], 'to'=>$asProject['active_to']]; } else $this->addError('Error while setting project: no project ID'); } private function updateField($sField, $oValue) { $bResult = ($this->oDb->updateRow(self::PROJ_TABLE, $this->getProjectId(), [$sField=>$oValue]) > 0); $this->setProjectInfo(); return $bResult; } public function delete() { $asResult = []; if($this->getProjectId() > 0) { $asFeedIds = $this->getFeedIds(); foreach($asFeedIds as $iFeedId) { $asResult['feed'][] = (new Feed($this->oDb, $iFeedId))->delete(); } $bDeleted = $this->oDb->deleteRow(self::PROJ_TABLE, $this->getProjectId()); $asResult['project'][] = [ 'id' => $this->getProjectId(), 'del' => $bDeleted, 'desc_lang_id' => $bDeleted?'':'error.commit_db', 'desc_lang_params' => [] ]; } else $asResult['project'][] = ['del'=>false, 'desc_lang_id'=>'error.impossible_value', 'desc_lang_params'=>[$this->getProjectId(), 'project ID']]; return $asResult; } public function isEditable() { return self::isModeEditable($this->getMode()); } public static function isModeEditable($sMode) { return ($sMode != self::MODE_HISTO); } }