db = $database; $this->resubmissionGateway = $resubmissionGateway; } /** * @param int $configId * * @return bool */ public function existsConfig($configId) { $sql = 'SELECT COUNT(wfk.id) AS `config_count` FROM `wiedervorlage_freifeld_konfiguration` AS `wfk` WHERE wfk.id = :config_id'; $configCount = (int)$this->db->fetchValue($sql, ['config_id' => (int)$configId]); return $configCount === 1; } /** * @param int $configId * * @throws TextFieldConfigNotFoundException * * @return array */ public function getConfigById($configId) { $sql = 'SELECT wfk.id, wfk.title, wfk.available_from_stage_id, wfk.required_from_stage_id, wfk.show_in_pipeline, wfk.show_in_tables FROM `wiedervorlage_freifeld_konfiguration` AS `wfk` WHERE wfk.id = :config_id'; $result = $this->db->fetchRow($sql, ['config_id' => (int)$configId]); if (empty($result)) { throw new TextFieldConfigNotFoundException(sprintf( 'Text field config not found: ID%s', $configId )); } if (empty($result['available_from_stage_id'])) { $result['available_from_stage_id'] = 0; } if (empty($result['required_from_stage_id'])) { $result['required_from_stage_id'] = 0; } $result['show_in_pipeline'] = (int)$result['show_in_pipeline'] === 1; $result['show_in_tables'] = (int)$result['show_in_tables'] === 1; return $result; } /** * @example Rückgabe: ['freifeld1' => 'Mein Freifeld 1', 'freifeld2' => 'Mein Freifeld 2'] * * @param int $viewId * * @return array */ public function getTextFieldsForTableView($viewId) { $stages = $this->resubmissionGateway->getStagesByView($viewId); $stageIds = array_column($stages, 'id'); if (empty($stageIds)) { return []; } $sql = 'SELECT CONCAT(\'freifeld\', wfk.id) AS name, wfk.title FROM `wiedervorlage_freifeld_konfiguration` AS `wfk` WHERE wfk.show_in_tables = 1 AND ( wfk.available_from_stage_id = 0 OR wfk.available_from_stage_id IN (:stages_ids) OR wfk.required_from_stage_id IN (:stages_ids) )'; return $this->db->fetchPairs($sql, ['stages_ids' => $stageIds]); } /** * @example Rückgabe: ['freifeld1' => 'Mein Freifeld 1', 'freifeld2' => 'Mein Freifeld 2'] * * @param int $viewId * * @return array */ public function getTextFieldsForPipelineView($viewId) { $stages = $this->resubmissionGateway->getStagesByView($viewId); $stageIds = array_column($stages, 'id'); if (empty($stageIds)) { return []; } $sql = 'SELECT CONCAT(\'freifeld\', wfk.id) AS name, wfk.title FROM `wiedervorlage_freifeld_konfiguration` AS `wfk` WHERE wfk.show_in_pipeline = 1 AND ( wfk.available_from_stage_id = 0 OR wfk.available_from_stage_id IN (:stages_ids) OR wfk.required_from_stage_id IN (:stages_ids) )'; return $this->db->fetchPairs($sql, ['stages_ids' => $stageIds]); } /** * Lädt alle Freitextfelder die in der übergebenen Stage ein Pflichtfeld sind * * @param int $stageId * * @return array */ public function getRequiredTextFieldsForStage($stageId) { // Schritt 1 // Alle Stage-IDs ermittlen für die wir die Freitextfelder laden sollen // d.h. alle Stages die in der Reihenfolge vor der aktuellen Stage kommen; inklusive der aktuellen Stage $validStages = $this->getStagesUntilStageId($stageId); $validStageIds = array_column($validStages, 'id'); // Schritt 2 // Alle Pflicht-Freitextfelder für die Stages aus Schritt 1 ermitteln $sql = 'SELECT wfk.id AS `config_id`, wfk.title AS `label`, wfk.available_from_stage_id, wfk.required_from_stage_id, ws.name AS `required_from_stage_name`, wfk.show_in_pipeline, wfk.show_in_tables FROM `wiedervorlage_freifeld_konfiguration` AS `wfk` LEFT JOIN `wiedervorlage_stages` AS `ws` ON wfk.required_from_stage_id = ws.id WHERE wfk.required_from_stage_id IN (:valid_stage_ids)'; return $this->db->fetchAll($sql, [ 'valid_stage_ids' => $validStageIds, ]); } /** * Lädt alle Stages die in der Reihenfolge vor der übergebenen Stage liegen * * @refactor ResubmissionGateway * * @param int $stageId * * @return array */ private function getStagesUntilStageId($stageId) { // Alle Stages in der gleichen View ermitteln $stageId = (int)$stageId; $stages = $this->resubmissionGateway->getSiblingStages($stageId); // Rang der übergebenen Stage ermitteln $currentRank = 0; foreach ($stages as $stage) { if ($stage['id'] === $stageId) { $currentRank = $stage['rank']; } } // Alle Stages filtern die VOR der übergebenen Stage liegen (inklusive der übergebenen Stage) $validStages = []; foreach ($stages as $stage) { if ($stage['rank'] <= $currentRank) { $validStages[] = $stage; } } return $validStages; } /** * Ermittelt alle Freifelder die das Verschieben einer Wiedervorlage blockieren * * @param int $resubmissionId * @param int $targetStageId * * @return array Empty array if none item is blocking */ public function getBlockingTextFieldsForTargetStage($resubmissionId, $targetStageId) { $resubmissionId = (int)$resubmissionId; $targetStageId = (int)$targetStageId; $textfields = $this->getTextFieldsForResubmission($resubmissionId); $blocking = []; foreach ($textfields as $textfield) { if (!empty($textfield['content'])) { continue; // Textfeld ist ausgefüllt > Textfeld darf in jede Stage geschoben werden } if ((int)$textfield['required_from_stage_id'] === 0) { continue; // Textfeld hat keine Fertigstellungs-Stage hinterlegt > Textfeld darf in jede Stage geschoben werden } $distance = $this->resubmissionGateway->getDistanceBetweenStages( $targetStageId, $textfield['required_from_stage_id'] ); if ($distance <= 0) { $blocking[] = [ 'config_id' => $textfield['config_id'], 'content_id' => $textfield['content_id'], 'label' => $textfield['label'], ]; } } return $blocking; } /** * Lädt alle Freitextfelder für eine Wiedervorlage * * @param int $resubmissionId * * @throws ResubmissionNotFoundException * * @return array */ public function getTextFieldsForResubmission($resubmissionId) { $stage = $this->resubmissionGateway->getStageByResubmission($resubmissionId); $viewId = (int)$stage['view_id']; // View-ID `0` ist zulässig // 1. Alle Stage-IDs ermittlen für die wir die Freitextfelder laden sollen // d.h. alle Stages die in der Reihenfolge vor der aktuellen Stage kommen; inklusive der aktuellen Stage $validStages = $this->getStagesUntilStageId($stage['id']); $validStageIds = array_column($validStages, 'id'); // 2. Alle Freitextfelder für die Stages aus Schritt 1 ermitteln $sql = 'SELECT wfk.id AS `config_id`, wfi.id AS `content_id`, wfk.title AS `label`, wfk.available_from_stage_id, wfk.required_from_stage_id, wfk.show_in_pipeline, wfk.show_in_tables FROM `wiedervorlage_freifeld_konfiguration` AS `wfk` LEFT JOIN `wiedervorlage_freifeld_inhalt` AS `wfi` ON wfi.resubmission_id = :resubmission_id LEFT JOIN `wiedervorlage_stages` AS ws1 ON wfk.required_from_stage_id = ws1.id LEFT JOIN `wiedervorlage_stages` AS ws2 ON wfk.available_from_stage_id = ws2.id WHERE wfk.available_from_stage_id = 0 OR wfk.available_from_stage_id IN (:valid_stage_ids) OR wfk.required_from_stage_id IN (:valid_stage_ids) ORDER BY wfk.required_from_stage_id != 0 DESC, ws1.sort, ws2.sort, wfk.title'; // Erklärung Sortierung: // 1. `wfk.required_from_stage_id != 0 DESC` = Felder mit Pflicht-Stage oben anzeigen // 2. `ws1.sort, ws2.sort` = Felder nach Reihenfolge der Stages anzeigen $textFields = $this->db->fetchAll($sql, [ 'resubmission_id' => $resubmissionId, 'valid_stage_ids' => $validStageIds, 'view_id' => $viewId, ]); // Freitextfeld-Inhalte ergänzen $contents = $this->getTextFieldContentsForResubmission($resubmissionId); foreach ($textFields as &$textField) { $configId = (int)$textField['config_id']; $textField['content'] = $contents[$configId]; } unset($textField); return $textFields; } /** * @param int $resubmissionId * * @return array */ private function getTextFieldContentsForResubmission($resubmissionId) { $columnNames = $this->getTextFieldColumnNames(); $contentsAll = $this->db->fetchRow( 'SELECT wfi.* FROM `wiedervorlage_freifeld_inhalt` AS `wfi` WHERE wfi.resubmission_id = :resubmission_id LIMIT 1', ['resubmission_id' => (int)$resubmissionId] ); $contents = []; foreach ($columnNames as $configId => $columnName) { if (isset($contentsAll[$columnName])) { $contents[$configId] = $contentsAll[$columnName]; } else { $contents[$configId] = null; } } return $contents; } /** * @param string|null $tableAlias * * @return array */ private function getTextFieldColumnNames($tableAlias = null) { $sql = 'SELECT wfk.id FROM `wiedervorlage_freifeld_konfiguration` AS `wfk` WHERE 1'; $configIds = $this->db->fetchCol($sql); $columnNames = []; $columnPrefix = $tableAlias !== null ? sprintf('%s.', $tableAlias) : ''; foreach ($configIds as $configId) { $columnNames[$configId] = sprintf('%sfreifeld%s', $columnPrefix, $configId); } return $columnNames; } }