diff --git a/application/config/dbskel.php b/application/config/dbskel.php new file mode 100644 index 000000000..dafdc0d31 --- /dev/null +++ b/application/config/dbskel.php @@ -0,0 +1,27 @@ +load->library('DBSkelLib'); + } + + /** + * Starts the DBSkel procedure + */ + public function start($step = null, $selectedDirectories = null) + { + // If the DBSkel procedure fails then exit with an error + // In this way it's possible to undestand from console what is the exit status of the procedure + $this->dbskellib->start($step, $selectedDirectories) === true ? exit(0) : exit(1); + } +} diff --git a/application/dbskel/fue/TBL_aktivitaet.php b/application/dbskel/fue/TBL_aktivitaet.php new file mode 100644 index 000000000..05027ba92 --- /dev/null +++ b/application/dbskel/fue/TBL_aktivitaet.php @@ -0,0 +1,27 @@ + array( + 'aktivitaet_kurzbz' => array( + 'comment' => 'I guess this is the PK', + 'type' => 'character varying(16)', + 'null' => false + ), + 'beschreibung' => array( + 'comment' => 'none', + 'type' => 'character varying(256)', + 'null' => false, + 'default' => "'Test string'" + ), + 'sort' => array( + 'comment' => 'nope', + 'type' => 'integer', + 'default' => 1 + ), + 'oe_kurzbz' => array( + 'comment' => 'uhm', + 'type' => 'character varying(32)' + ) + ), + 'comment' => 'Timesheet SLA Activity' +); diff --git a/application/dbskel/fue/constraints.php b/application/dbskel/fue/constraints.php new file mode 100644 index 000000000..a3e534cf1 --- /dev/null +++ b/application/dbskel/fue/constraints.php @@ -0,0 +1,8 @@ + 'ALTER TABLE fue.tbl_aktivitaet ADD CONSTRAINT pk_tbl_aktivitaet PRIMARY KEY (aktivitaet_kurzbz)', + 'fk_projekt_oe' => 'ALTER TABLE fue.tbl_aktivitaet ADD CONSTRAINT fk_test FOREIGN KEY (oe_kurzbz) REFERENCES public.tbl_organisationseinheit (oe_kurzbz)', + 'uk_beschreibung' => 'ALTER TABLE fue.tbl_aktivitaet ADD CONSTRAINT uk_beschreibung UNIQUE (beschreibung)', + 'testchk' => 'ALTER TABLE fue.tbl_aktivitaet ADD CONSTRAINT testchk CHECK (sort > 0)' +); diff --git a/application/dbskel/fue/extra.sql b/application/dbskel/fue/extra.sql new file mode 100644 index 000000000..3d826b40f --- /dev/null +++ b/application/dbskel/fue/extra.sql @@ -0,0 +1 @@ +SELECT 'Extra file' AS justatest; diff --git a/application/dbskel/fue/functions.php b/application/dbskel/fue/functions.php new file mode 100644 index 000000000..f3dab4498 --- /dev/null +++ b/application/dbskel/fue/functions.php @@ -0,0 +1,19 @@ + + 'CREATE OR REPLACE FUNCTION fue.get_highest_content_version(bigint) RETURNS smallint AS $$ + DECLARE i_content_id ALIAS FOR $1; + DECLARE rec RECORD; + BEGIN + + SELECT INTO rec version + FROM campus.tbl_contentsprache + WHERE content_id = i_content_id + ORDER BY version desc + LIMIT 1; + + RETURN rec.version; + END; + $$ LANGUAGE plpgsql;' +); diff --git a/application/dbskel/fue/grants.sql b/application/dbskel/fue/grants.sql new file mode 100644 index 000000000..cdc8c9c95 --- /dev/null +++ b/application/dbskel/fue/grants.sql @@ -0,0 +1,20 @@ +----------------------------------------------------- +-- Revokes all privileges from all granted users +----------------------------------------------------- +REVOKE ALL PRIVILEGES ON SCHEMA fue FROM vilesci; +REVOKE ALL ON ALL TABLES IN SCHEMA fue FROM vilesci; +REVOKE ALL ON ALL SEQUENCES IN SCHEMA fue FROM vilesci; +REVOKE ALL ON ALL FUNCTIONS IN SCHEMA fue FROM vilesci; + +---------------------------------------------------------------------------------------------------- +-- Gives the desired privileges to the chosen users (with great power comes great responsibility!) +---------------------------------------------------------------------------------------------------- + +-- Schema privileges +GRANT ALL ON SCHEMA fue TO vilesci; +GRANT USAGE ON SCHEMA fue TO web; +GRANT USAGE ON SCHEMA fue TO wawi; + +-- Sequences privileges +GRANT SELECT,UPDATE ON SEQUENCE fue.seq_projekt_dokument_projekt_dokument_id TO vilesci; +GRANT SELECT,UPDATE ON SEQUENCE fue.seq_projekt_dokument_projekt_dokument_id TO web; diff --git a/application/dbskel/fue/schema.sql b/application/dbskel/fue/schema.sql new file mode 100644 index 000000000..1dc28d796 --- /dev/null +++ b/application/dbskel/fue/schema.sql @@ -0,0 +1,4 @@ +-- Create the schema if not exists +CREATE SCHEMA IF NOT EXISTS fue; +-- Comment schema +COMMENT ON SCHEMA fue IS 'Projectmanagement'; diff --git a/application/dbskel/fue/sequences.php b/application/dbskel/fue/sequences.php new file mode 100644 index 000000000..98a1ca60b --- /dev/null +++ b/application/dbskel/fue/sequences.php @@ -0,0 +1,11 @@ + + 'CREATE SEQUENCE fue.seq_projekt_dokument_projekt_dokument_id + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1;' +); diff --git a/application/dbskel/fue/views.php b/application/dbskel/fue/views.php new file mode 100644 index 000000000..69b911714 --- /dev/null +++ b/application/dbskel/fue/views.php @@ -0,0 +1,50 @@ + + 'CREATE OR REPLACE VIEW fue.vw_projektressourcen ( + projekt_ressource_id, + projekt_kurzbz, + projektphase_id, + projektphase, + typ, + ressource_id, + ressource, + funktion_kurzbz, + start, + ende, + oe_kurzbz, + projektbudget, + aufwandstyp_kurzbz, + projektphase_fk, + phasenbudget, + personentage, + nummer, + titel, + aufwand + ) + AS + SELECT tpr.projekt_ressource_id, + COALESCE(tpr.projekt_kurzbz, tpp.projekt_kurzbz) AS projekt_kurzbz, + tpr.projektphase_id, + tpp.bezeichnung AS projektphase, + COALESCE(tpp.typ, \'Projekt\'::character varying) AS typ, + tpr.ressource_id, + tr.bezeichnung AS ressource, + tpr.funktion_kurzbz, + COALESCE(tpp.start, tp.beginn) AS start, + COALESCE(tpp.ende, tp.ende) AS ende, + tp.oe_kurzbz, + tp.budget AS projektbudget, + tp.aufwandstyp_kurzbz, + tpp.projektphase_fk, + tpp.budget AS phasenbudget, + tpp.personentage, + tp.nummer, + tp.titel, + tpr.aufwand + FROM fue.tbl_projekt_ressource tpr + JOIN fue.tbl_ressource tr USING (ressource_id) + LEFT JOIN fue.tbl_projekt tp USING (projekt_kurzbz) + LEFT JOIN fue.tbl_projektphase tpp USING (projektphase_id);' +); diff --git a/application/dbskel/index.html b/application/dbskel/index.html new file mode 100644 index 000000000..b702fbc39 --- /dev/null +++ b/application/dbskel/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/libraries/CallerLib.php b/application/libraries/CallerLib.php index 0b46cf0c6..82883cac4 100644 --- a/application/libraries/CallerLib.php +++ b/application/libraries/CallerLib.php @@ -19,7 +19,6 @@ class CallerLib private static $RESOURCES_BLACK_LIST = array( 'CallerLib', // disabled self loading 'LogLib', // hardly usefull and virtually dangerous - 'MigrationLib', // virtually dangerous, DB manipulation 'FilesystemLib', // virtually dangerous, direct access to file system 'PermissionLib', // usefull? 'PersonLogLib' diff --git a/application/libraries/DBSkelLib.php b/application/libraries/DBSkelLib.php new file mode 100644 index 000000000..1d556d9a4 --- /dev/null +++ b/application/libraries/DBSkelLib.php @@ -0,0 +1,1251 @@ +_ci =& get_instance(); // get code igniter instance + + // Loads DB conns and confs using system settings + $this->_ci->load->database('system'); + + // Loads dbskel configs + $this->_ci->config->load('dbskel'); + + // Loads library EPrintfLib + $this->_ci->load->library('EPrintfLib'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Starts the DBSkel procedure + * Returns false on failure and true on success + * All errors/warnings/infos are printed here using EPrintfLib + * Accept the step parameter that can be used to run only a wanted step + */ + public function start($steps, $selectedDirectories) + { + $start = false; + + // Checks if DBSkel is enabled + if ($this->_ci->config->item(self::CONF_ENABLED) === true) + { + // Checks if the given steps parameter is fine + if ($this->_checkParameterStep($steps)) + { + $this->_printSchemaSeparator(); + + $this->_printRunningMode(); + + // By default perform all steps + $stepsArray = range(1, self::MAX_STEPS); + // If steps parameter is given then use it to select the steps to be performed + if ($steps != null) $stepsArray = explode(self::SEPARATOR, $steps); + + // Gets all the directories in application/dbskel + $directories = glob(self::DBSKEL_DIR.'*', GLOB_ONLYDIR); + + // Checks if the selectedDirectories parameter is fine + if ($this->_checkParameterSelectedDirectories($selectedDirectories, $directories)) + { + $start = $this->_processDirectories($directories, $stepsArray); + + $this->_printSchemaSeparator(); + } + } + } + else + { + $this->_printInfo('DBSkel is NOT enabled'); + } + + return $start; + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Process every single directory present in dbskel directory + */ + private function _processDirectories($directories, $stepsArray) + { + $processDirectories = false; // failure by default + + // For each directory + foreach ($directories as $directory) + { + $processDirectories = false; // Reset to false at the beginning of each loop + + $this->_printSchemaSeparator(); + $this->_printInfo('Found directory >>> '.basename($directory).' <<<'); + + // NOTE: the order in which these methods are called has a meaning! + // If a step fails then the loop is stopped + + // 0 - Checks file naming convention in current directory + // NOTE: no need to check a failure! NOT a blocking check!! Always performed!!! + $this->_checkFilenaming($directory); + + $this->_printFileSeparator(); + + // 1 - Process schema file + if (in_array(self::STEP_SCHEMA, $stepsArray)) + { + if (!$this->_processSchemaFile($directory)) break; + + $this->_printFileSeparator(); + } + + // 2 - Process sequence file + if (in_array(self::STEP_SEQUENCES, $stepsArray)) + { + if (!$this->_processSequencesFile($directory)) break; + + $this->_printFileSeparator(); + } + + // 3 - Process table files + if (in_array(self::STEP_TABLES, $stepsArray)) + { + if (!$this->_processTableFiles($directory)) break; + + $this->_printFileSeparator(); + } + + // 4 - Process constraints + if (in_array(self::STEP_CONSTRAINTS, $stepsArray)) + { + if (!$this->_processConstraintsFile($directory)) break; + + $this->_printFileSeparator(); + } + + // 5 - Process views file + if (in_array(self::STEP_VIEWS, $stepsArray)) + { + if (!$this->_processViewsFile($directory)) break; + + $this->_printFileSeparator(); + } + + // 6 - Process functions file + if (in_array(self::STEP_FUNCTIONS, $stepsArray)) + { + if (!$this->_processFunctionsFile($directory)) break; + + $this->_printFileSeparator(); + } + + // 7 - Process grants file + if (in_array(self::STEP_GRANTS, $stepsArray)) + { + if (!$this->_processGrantsFile($directory)) break; + + $this->_printFileSeparator(); + } + + // 8 - Process extra file + if (in_array(self::STEP_EXTRA, $stepsArray)) + { + if (!$this->_processExtraFile($directory)) break; + } + + $processDirectories = true; // If all the steps ends successfully + + $this->_printSchemaSeparator(); + } + + return $processDirectories; + } + + /** + * Checks file names are compliant with the file naming convention + */ + private function _checkFilenaming($directory) + { + $files = array_filter(glob($directory.'/*'), 'is_file'); + + // For each file + foreach ($files as $file) + { + $fileName = basename($file); // File name + // If the file name is NOT compliant with the file naming convention + if (!$this->_isFilenameValid($fileName)) + { + $this->_printInfo('Not valid file name, it is going to be ignored: '.$fileName); + } + } + } + + /** + * Checks if the file name is compliant with the file naming convention + */ + private function _isFilenameValid($fileName) + { + return $fileName == self::SCHEMA_FILENAME // Schema file + || $fileName == self::SEQUENCES_FILENAME // Sequences file + || (substr($fileName, 0, strlen(self::TABLE_PREFIX)) == self::TABLE_PREFIX + && substr($fileName, -4, strlen(self::PHP_EXT)) == self::PHP_EXT) // Table files + || $fileName == self::CONSTRAINTS_FILENAME // Constraints file + || $fileName == self::VIEWS_FILENAME // Views file + || $fileName == self::FUNCTIONS_FILENAME // Function file + || $fileName == self::GRANTS_FILENAME // Grants file + || $fileName == self::EXTRA_FILENAME; // Extra file + } + + /** + * Process the schema file + */ + private function _processSchemaFile($directory) + { + // Looks for a schema file + $files = array_filter(glob($directory.'/'.self::SCHEMA_FILENAME), 'is_file'); + + // If a schema file is found... + if (count($files) > 0) + { + $this->_printMessage('Found schema file: '.$files[0]); + + //...process it! + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> would be executed in new and diff mode'); + } + else // new or diff mode + { + return $this->_execSQLFile($files[0]); + } + } + else + { + $this->_printMessage('No schema file found'); + } + + return true; // If no files are found then go forward -> is a success + } + + /** + * Process sequences file + * - Looks for sequences present in current schema, then sequences that are NOT present in php file are dropped (diff mode only) + * - Looks for sequences present in php files, then sequences that are NOT present in database are installed + */ + private function _processSequencesFile($directory) + { + // Looks for a sequences file + $files = array_filter(glob($directory.'/'.self::SEQUENCES_FILENAME), 'is_file'); + + // If a sequences file is found... + if (count($files) > 0) + { + $this->_printMessage('Found sequences file: '.$files[0]); + + //...process it! + require_once($files[0]); // Read sequences file + $schema = basename($directory); // retrieves schema name from directory path + $dbSequencesArray = $this->_listSequencesBySchema($schema); // get list of sequences currently present in DB schema + + // Loops through list of sequences currently present in database + foreach ($dbSequencesArray as $dbSequence) + { + // If NOT in new mode and if the sequence present in database is NOT present in the list of sequences from php file + if (!$this->_isNewMode() && !array_key_exists($dbSequence, $sequencesArray)) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> sequence '.$dbSequence.' NOT found in sequences file >> would be removed in diff mode'); + } + elseif ($this->_isDiffMode()) // only if in diff mode + { + // Then drop it and objects that depends on it from database! If it fails then ends execution + if (!$this->_execQuery(sprintf('DROP SEQUENCE %s.%s CASCADE', $schema, $dbSequence))) + { + $this->_printError('Error occurred while dropping sequence: '.$dbSequence); + return false; + } + else + { + $this->_printMessage('Sequence dropped successfully: '.$dbSequence); + } + } + } + } + + // Loops through list of sequences from php file + foreach ($sequencesArray as $sequenceName => $sequenceSQL) + { + // If the sequence from php file is NOT present in database + if (!in_array($sequenceName, $dbSequencesArray)) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> sequence '.$sequenceName.' NOT found database >> would be added in new and diff mode'); + } + else + { + // Then install it! If it fails then ends execution + if (!$this->_execQuery($sequenceSQL)) + { + $this->_printError('Error occurred while adding sequence: '.$sequenceName); + return false; + } + else + { + $this->_printMessage('Sequence added successfully: '.$sequenceName); + } + } + } + else + { + $this->_printMessage('Sequence already present in database: '.$sequenceName); + } + } + } + else + { + $this->_printMessage('No sequences file found'); + } + + return true; // If ends of procedure with no failures or no files are found then is a success + } + + /** + * Process table files + */ + private function _processTableFiles($directory) + { + // Looks for table files + $files = array_filter(glob($directory.'/'.self::TABLE_PREFIX.'*'.self::PHP_EXT), 'is_file'); + + // If table files are found... + if (count($files) > 0) + { + //...process them! + $schema = basename($directory); // retrieves schema name from directory path + $dbTablesArray = $this->_listTablesBySchema($schema); // get list of tables currently present in DB schema + + // For each table file + foreach ($files as $file) + { + $this->_printMessage('Found table file: '.$file); + + require_once($file); // Read table file + + // Loops through list of tables currently present in database + foreach ($dbTablesArray as $dbTable) + { + // If NOT in new mode and if the table present in database is NOT present in the php table file + if (!$this->_isNewMode() && !array_key_exists($dbTable, $tableArray)) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> table '.$dbTable.' NOT found in table file >> would be removed in diff mode'); + } + elseif ($this->_isDiffMode()) // only if in diff mode + { + // Then drop it! If it fails then ends execution + if (!$this->_execQuery(sprintf('DROP TABLE %s.%s', $schema, $dbTable))) + { + $this->_printError('Error occurred while dropping table: '.$dbTable); + return false; + } + else + { + $this->_printMessage('Table dropped successfully: '.$dbTable); + } + } + } + } + + // Retrieves all the elements from the $tableArray except the element 'comment' + $tableElements = array_keys(array_diff_key($tableArray, array(self::T_COMMENT => null))); + if (is_array($tableElements) && count($tableElements) == 1) // If there is only one element left... + { + $tableName = $tableElements[0]; // ...then it is the name of the table + + // If the table from php file is NOT present in database + if (!in_array($tableName, $dbTablesArray)) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> table '.$tableName.' would be created in new and diff mode'); + } + else // new and diff mode + { + // Then create the new table! If it fails then ends execution + if ($this->_createTable($schema, $tableArray)) + { + $this->_printMessage('Table created successfully: '.$tableName); + } + else + { + $this->_printError('Error occurred while creating a new table: '.$tableName); + return false; + } + } + } + else // if table is already present in database + { + $this->_printMessage('Table already present in database: '.$tableName); + + // Manage the differences between the table present in database and the one present in php file + return $this->_manageTableColumns($schema, $tableArray); + } + } + else // otherwise the array present in the php table file is not well formatted + { + $this->_printError('Table file with a bad format is going to be ignored: '.$file); + } + } + } + else + { + $this->_printMessage('No table files found'); + } + + return true; // If no files are found then go forward -> is a success + } + + /** + * Process constraints file + * - Looks for constraints present in current schema, then constraints that are NOT present in php file are dropped (diff mode only) + * - Looks for constraints present in php files, then constraints that are NOT present in database are installed + */ + private function _processConstraintsFile($directory) + { + // Looks for a constraints file + $files = array_filter(glob($directory.'/'.self::CONSTRAINTS_FILENAME), 'is_file'); + + // If a constraints file is found... + if (count($files) > 0) + { + $this->_printMessage('Found constraints file: '.$files[0]); + + //...process it! + require_once($files[0]); // Read constraints file + $schema = basename($directory); // retrieves schema name from directory path + $dbConstraintsArray = $this->_listConstraintsBySchema($schema); // get list of constraints currently present in DB schema + $dbConstraintsNamesArray = array(); // Contains only the names of the constraints + + // Loops through list of constraints currently present in database + foreach ($dbConstraintsArray as $dbConstraint) + { + $dbConstraintsNamesArray[] = $dbConstraint['name']; // Copy only the name of the constraint + + // If NOT in new mode and if the constraint present in database is NOT present in the list of constraints from php file + if (!$this->_isNewMode() && !array_key_exists($dbConstraint['name'], $constraintsArray)) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> constraint '.$dbConstraint['name'].' NOT found in constraints file >> would be removed in diff mode'); + } + elseif ($this->_isDiffMode()) // only if in diff mode + { + // Then drop it and objects that depends on it from database! If it fails then ends execution + if (!$this->_execQuery(sprintf('ALTER TABLE %s.%s DROP CONSTRAINT %s', $schema, $dbConstraint['table'], $dbConstraint['name']))) + { + $this->_printError('Error occurred while dropping constraint: '.$dbConstraint['name']); + return false; + } + else + { + $this->_printMessage('Constraint dropped successfully: '.$dbConstraint['name']); + } + } + } + } + + // Loops through list of constraints from php file + foreach ($constraintsArray as $constraintName => $constraintSQL) + { + // If the constraint from php file is NOT present in database + if (!in_array($constraintName, $dbConstraintsNamesArray)) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> constraint '.$constraintName.' would be added in new and diff mode'); + } + else + { + // Then install it! If it fails then ends execution + if (!$this->_execQuery($constraintSQL)) + { + $this->_printError('Error occurred while adding constraint: '.$constraintName); + return false; + } + else + { + $this->_printMessage('Constraint added successfully: '.$constraintName); + } + } + } + else + { + $this->_printMessage('Constraint already present in database: '.$constraintName); + } + } + } + else + { + $this->_printMessage('No constraints file found'); + } + + return true; // If ends of procedure with no failures or no files are found then is a success + } + + /** + * Process views file + * - Looks for views present in current schema, then views that are NOT present in php file are dropped (diff mode only) + * - Looks for views present in php files and install them all + */ + private function _processViewsFile($directory) + { + // Looks for a views file + $files = array_filter(glob($directory.'/'.self::VIEWS_FILENAME), 'is_file'); + + // If a views file is found... + if (count($files) > 0) + { + $this->_printMessage('Found views file: '.$files[0]); + + //...process it! + require_once($files[0]); // Read views file + $schema = basename($directory); // retrieves schema name from directory path + $dbViewsArray = $this->_listViewsBySchema($schema); // get list of views currently present in DB schema + + // Loops through list of views currently present in database + foreach ($dbViewsArray as $dbView) + { + // If NOT in new mode and if the view present in database is NOT present in the list of views from php file + if (!$this->_isNewMode() && !array_key_exists($dbView, $viewsArray)) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> view '.$dbView.' NOT found in views file >> would be removed in diff mode'); + } + elseif ($this->_isDiffMode()) // only if in diff mode + { + // Then drop it and objects that depends on it from database! If it fails then ends execution + if (!$this->_execQuery(sprintf('DROP VIEW %s.%s CASCADE', $schema, $dbView))) + { + $this->_printError('Error occurred while dropping view: '.$dbView); + return false; + } + else + { + $this->_printMessage('View dropped successfully: '.$dbView); + } + } + } + } + + // Loops through list of views from php file + foreach ($viewsArray as $viewName => $viewSQL) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> view '.$viewName.' would be added in new and diff mode'); + } + else + { + // Then install it! If it fails then ends execution + if (!$this->_execQuery($viewSQL)) + { + $this->_printError('Error occurred while adding view: '.$viewName); + return false; + } + else + { + $this->_printMessage('View added successfully: '.$viewName); + } + } + } + } + else + { + $this->_printMessage('No views file found'); + } + + return true; // If ends of procedure with no failures or no files are found then is a success + } + + /** + * Process functions file + * - Looks for functions present in current schema, then functions that are NOT present in php file are dropped (diff mode only) + * - Looks for functions present in php files and install them all + */ + private function _processFunctionsFile($directory) + { + // Looks for a functions file + $files = array_filter(glob($directory.'/'.self::FUNCTIONS_FILENAME), 'is_file'); + + // If a functions file is found... + if (count($files) > 0) + { + $this->_printMessage('Found functions file: '.$files[0]); + + //...process it! + require_once($files[0]); // Read functions file + $schema = basename($directory); // retrieves schema name from directory path + $dbFunctionsArray = $this->_listFunctionsBySchema($schema); // get list of functions currently present in DB schema + + // Loops through list of functions currently present in database + foreach ($dbFunctionsArray as $dbFunction) + { + // If NOT in new mode and if the function present in database is NOT present in the list of functions from php file + if (!$this->_isNewMode() && !array_key_exists($dbFunction, $functionsArray)) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> function '.$dbFunction.' NOT found in fucntions file >> would be removed in diff mode'); + } + elseif ($this->_isDiffMode()) // only if in diff mode + { + // Then drop it and objects that depends on it from database! If it fails then ends execution + if (!$this->_execQuery(sprintf('DROP FUNCTION %s.%s CASCADE', $schema, $dbFunction))) + { + $this->_printError('Error occurred while dropping function: '.$dbFunction); + return false; + } + else + { + $this->_printMessage('Function dropped successfully: '.$dbFunction); + } + } + } + } + + // Loops through list of functions from php file + foreach ($functionsArray as $functionName => $functionSQL) + { + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> view '.$functionName.' would be added in new and diff mode'); + } + else + { + // Then install it! If it fails then ends execution + if (!$this->_execQuery($functionSQL)) + { + $this->_printError('Error occurred while adding function: '.$functionName); + return false; + } + else + { + $this->_printMessage('Function added successfully: '.$functionName); + } + } + } + } + else + { + $this->_printMessage('No functions file found'); + } + + return true; // If ends of procedure with no failures or no files are found then is a success + } + + /** + * Process grants file + */ + private function _processGrantsFile($directory) + { + // Looks for a grants file + $files = array_filter(glob($directory.'/'.self::GRANTS_FILENAME), 'is_file'); + + // If a grants file is found... + if (count($files) > 0) + { + $this->_printMessage('Found grants file: '.$files[0]); + + //...process it! + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> would be executed in new and diff mode'); + } + else // new or diff mode + { + return $this->_execSQLFile($files[0]); + } + } + else + { + $this->_printMessage('No grants file found'); + } + + return true; // If no files are found then go forward -> is a success + } + + /** + * Process extra file + */ + private function _processExtraFile($directory) + { + // Looks for an extra file + $files = array_filter(glob($directory.'/'.self::EXTRA_FILENAME), 'is_file'); + + // If an extra file is found... + if (count($files) > 0) + { + $this->_printMessage('Found extra file: '.$files[0]); + + //...process it! + if ($this->_isDryrunMode()) // If dry run mode enabled + { + $this->_printInfo('Dry run >> would be executed in new and diff mode'); + } + else // new or diff mode + { + return $this->_execSQLFile($files[0]); + } + } + else + { + $this->_printMessage('No extra file found'); + } + + return true; // If no files are found then go forward -> is a success + } + + /** + * Load SQL from a file and then execute such SQL + */ + private function _execSQLFile($file) + { + $sql = file_get_contents($file); // Read the file content + if ($sql === false) // If failed + { + $this->_printError('Error occurred while reading file: '.$file); + } + else // otherwise + { + // Exec query + if ($this->_execQuery($sql) == false) // if failed + { + $this->_printError('Error occurred while executing SQL from file: '.$file); + } + else // otherwise + { + $this->_printMessage('Successfully executed SQL from file: '.$file); + return true; + } + } + + return false; + } + + /** + * Checks if the running mode is 'dryrun' + */ + private function _isDryrunMode() + { + return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_DRYRUN; + } + + /** + * Checks if the running mode is 'diff' + */ + private function _isDiffMode() + { + return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_DIFF; + } + + /** + * Checks if the running mode is 'new' + */ + private function _isNewMode() + { + return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_NEW; + } + + /** + * Checks if the parameter step is correct + */ + private function _checkParameterStep($steps) + { + if ($steps != null) // if it was given + { + $stepsArray = explode(self::SEPARATOR, $steps); // split the string in an array + foreach ($stepsArray as $step) + { + if (!is_numeric($step)) // if it is not a number + { + $this->_ci->eprintflib->printError('The given parameter must be a number or a string in the following format: 1:3:5'); + return false; + } + elseif ($step > self::MAX_STEPS) // if it is a number but > MAX_STEPS + { + $this->_ci->eprintflib->printError('The maximun value fot this parameter is: '.self::MAX_STEPS); + return false; + } + elseif ($step < 1) // if it is a number but < 1 + { + $this->_ci->eprintflib->printError('The minimum value fot this parameter is 1'); + return false; + } + } + } + + return true; + } + + /** + * Checks if the parameter selectedDirectories is correct and stores the result in $directories + */ + private function _checkParameterSelectedDirectories($selectedDirectories, &$directories) + { + if ($selectedDirectories != null) + { + $selectedDirectoriesArray = explode(self::SEPARATOR, $selectedDirectories); + + $found = true; + + foreach ($selectedDirectoriesArray as $key => $value) + { + $selectedDirectoriesArray[$key] = self::DBSKEL_DIR.$value; + + if (!in_array(self::DBSKEL_DIR.$value, $directories)) + { + $found = false; + break; + } + } + + if ($found) + { + $directories = $selectedDirectoriesArray; + } + else + { + $this->_printError('One or more of the given directories does NOT exist'); + return false; + } + } + + return true; + } + + //------------------------------------------------------------------------------------------------------------------ + // Private database methods + + /** + * Executes the given query + */ + private function _execQuery($query) + { + if (!@$this->_ci->db->simple_query($query)) + { + $error = $this->_ci->db->error(); + if (is_array($error) && isset($error['message'])) + { + $this->_printError($error['message']); + } + + return false; + } + + return true; + } + + /** + * Retrieves all the sequences present in the given database schema + */ + private function _listSequencesBySchema($schema) + { + $sequencesArray = array(); + $query = sprintf('SELECT sequence_name + FROM information_schema.sequences + WHERE sequence_schema = \'%s\'', $schema); + + if ($sequences = @$this->_ci->db->query($query)) + { + foreach ($sequences->result() as $sequence) + { + $sequencesArray[] = $sequence->sequence_name; + } + } + + return $sequencesArray; + } + + /** + * Retrieves all the tables present in the given database schema + */ + private function _listTablesBySchema($schema) + { + $tablesArray = array(); + $query = sprintf('SELECT table_name + FROM information_schema.tables + WHERE table_type = \'BASE TABLE\' + AND table_schema = \'%s\'', $schema); + + if ($tables = @$this->_ci->db->query($query)) + { + foreach ($tables->result() as $table) + { + $tablesArray[] = $table->table_name; + } + } + + return $tablesArray; + } + + /** + * Retrieves all the constraints present in the given database schema + * Returns an array with all the constraints, each element of the array is an array with two elements: + * - name: the name of the constraint + * - table: the name of the table where the constraint is applied + * NOTE: does not retrieve NOT NULL constraints + */ + private function _listConstraintsBySchema($schema) + { + $constraintsArray = array(); + $query = sprintf('SELECT constraint_name, + table_name + FROM information_schema.table_constraints + WHERE table_schema = \'%s\' + AND constraint_name NOT LIKE \'%%_not_null\'', $schema); // avoid to retrieve NOT NULL constraints + + if ($constraints = @$this->_ci->db->query($query)) + { + foreach ($constraints->result() as $constraint) + { + $constraintsArray[] = array('name' => $constraint->constraint_name, 'table' => $constraint->table_name); + } + } + + return $constraintsArray; + } + + /** + * Retrieves all the views present in the given database schema + */ + private function _listViewsBySchema($schema) + { + $viewsArray = array(); + $query = sprintf('SELECT table_name + FROM information_schema.views + WHERE table_schema = \'%s\'', $schema); + + if ($views = @$this->_ci->db->query($query)) + { + foreach ($views->result() as $view) + { + $viewsArray[] = $view->table_name; + } + } + + return $viewsArray; + } + + /** + * Retrieves all the functions present in the given database schema + */ + private function _listFunctionsBySchema($schema) + { + $functionsArray = array(); + $query = sprintf('SELECT routine_name + FROM information_schema.routines + WHERE specific_schema != \'pg_catalog\' + AND specific_schema != \'information_schema\' + AND routine_schema = \'%s\'', $schema); + + if ($functions = @$this->_ci->db->query($query)) + { + foreach ($functions->result() as $function) + { + $functionsArray[] = $function->routine_name; + } + } + + return $functionsArray; + } + + /** + * Retrieves all the columns from a database table + */ + private function _listColumns($schema, $table) + { + $columnsArray = array(); + $query = sprintf('SELECT column_name AS name, + data_type AS type, + column_default AS default, + is_nullable AS nullable, + character_maximum_length AS string_length, + numeric_precision AS number_length + FROM information_schema.columns + WHERE table_schema = \'%s\' + AND table_name = \'%s\'', $schema, $table); + + if ($columns = @$this->_ci->db->query($query)) + { + foreach ($columns->result() as $column) + { + $columnsArray[] = $column->routine_name; + } + } + + return $columnsArray; + } + + /** + * Creates a new table in database using the given schema and an array that defines the table structure + */ + private function _createTable($schema, $tableArray) + { + $tableName = ''; + $tableComment = ''; + $tableStructure = null; + + // For each element of the table array from the php file + foreach ($tableArray as $key => $value) + { + if ($key == self::T_COMMENT) // If it is the comment element + { + $tableComment = $value; + } + else // otherwise is the table structure element + { + $tableName = $key; + $tableStructure = $value; + } + } + + // Query to create a table + $query = sprintf('CREATE TABLE %s.%s (', $schema, $tableName); + // Query to comment the table and its columns + $queryComment = sprintf('COMMENT ON TABLE %s.%s IS \'%s\';', $schema, $tableName, $tableComment); + + // For each element of the table structure + foreach ($tableStructure as $colName => $colStructure) + { + $notNull = ''; // by default the column could be null + if (isset($colStructure[self::T_NULL]) && $colStructure[self::T_NULL] === false) + { + $notNull = 'NOT NULL'; // set to NOT NULL + } + + $default = ''; // by default there is no default for a column + if (isset($colStructure[self::T_DEFAULT])) + { + $default = 'DEFAULT '.$colStructure[self::T_DEFAULT]; // set as given by the table structure + } + + // Part of the query related to this column + $query .= sprintf('%s %s %s %s,', $colName, $colStructure[self::T_TYPE], $notNull, $default); + + // If a comment is present for this column then the query is built + if (isset($colStructure[self::T_COMMENT])) + { + $queryComment .= sprintf('COMMENT ON COLUMN %s.%s.%s IS \'%s\';', $schema, $tableName, $colName, $colStructure[self::T_COMMENT]); + } + } + + // Removes the last comma from the query + $query = substr($query, 0, strlen($query) - 1); + + // Close the round bracket + $query .= ');'; + + return $this->_execQuery($query.$queryComment); // executes query and returns its result + } + + /** + * TODO + * Changes the structure of a table using the given schema and an array that defines the table structure + */ + private function _manageTableColumns($schema, $tableArray) + { + $tableName = ''; + $tableComment = ''; + $tableStructure = null; + + // For each element of the table array from the php file + foreach ($tableArray as $key => $value) + { + if ($key == self::T_COMMENT) // If it is the comment element + { + $tableComment = $value; + } + else // otherwise is the table structure element + { + $tableName = $key; + $tableStructure = $value; + } + } + + // Comments the table + $queryComment = sprintf('COMMENT ON TABLE %s.%s IS \'%s\';', $schema, $tableName, $tableComment); + if ($this->_isDryrunMode()) + { + $this->_printInfo('Dry run >> table '.$tableName.' would be commented with: '.$queryComment); + } + else // new and diff mode + { + if (!$this->_execQuery($queryComment)) + { + $this->_printError('Error occurred while commenting table: '.$tableName); + return false; + } + else + { + $this->_printMessage('Table successfully commented: '.$tableName); + } + } + + // Retrieves the list of columns and their attributes from database + $dbTableColumns = $this->_listColumns($schema, $tableName); + + // For each element of the table structure + foreach ($tableStructure as $colName => $colStructure) + { + $notNull = ''; // by default the column could be null + if (isset($colStructure[self::T_NULL]) && $colStructure[self::T_NULL] === false) + { + $notNull = 'NOT NULL'; // set to NOT NULL + } + + $default = ''; // by default there is no default for a column + if (isset($colStructure[self::T_DEFAULT])) + { + $default = 'DEFAULT '.$colStructure[self::T_DEFAULT]; // set as given by the table structure + } + + // Part of the query related to this column + $query = sprintf('%s %s %s %s,', $colName, $colStructure[self::T_TYPE], $notNull, $default); + + // Comments a column + if (isset($colStructure[self::T_COMMENT])) + { + if ($this->_isDryrunMode()) + { + $this->_printInfo('Dry run >> column '.$tableName.'.'.$colName.' would be commented with: '.$colStructure[self::T_COMMENT]); + } + else // new and diff mode + { + $queryComment = sprintf('COMMENT ON COLUMN %s.%s.%s IS \'%s\';', $schema, $tableName, $colName, $colStructure[self::T_COMMENT]); + if (!$this->_execQuery($queryComment)) + { + $this->_printError('Error occurred while commenting column: '.$tableName.'.'.$colName); + return false; + } + else + { + $this->_printMessage('Column successfully commented: '.$tableName.'.'.$colName); + } + } + } + } + + return true; + } + + //------------------------------------------------------------------------------------------------------------------ + // Private output methods + + /** + * + */ + private function _printInfo($string) + { + $this->_ci->eprintflib->printInfo($string); + } + + /** + * + */ + private function _printError($string) + { + $this->_ci->eprintflib->printError($string); + } + + /** + * + */ + private function _printMessage($string) + { + $this->_ci->eprintflib->printMessage($string); + } + + /** + * + */ + private function _printSchemaSeparator() + { + $this->_printInfo('--------------------------------------------------------------------------------------------'); + } + + /** + * + */ + private function _printFileSeparator() + { + $this->_printMessage('--------------------------------------------------------------------------------------------'); + } + + /** + * + */ + private function _printRunningMode() + { + if ($this->_isDryrunMode()) $this->_printInfo('>> DBSkel is running in dry run mode <<'); + elseif ($this->_isNewMode()) $this->_printInfo('>> DBSkel is running in new mode <<'); + elseif ($this->_isDiffMode()) $this->_printInfo('>> DBSkel is running in diff mode <<'); + } +} diff --git a/application/libraries/MigrationLib.php b/application/libraries/MigrationLib.php deleted file mode 100644 index a461d7a82..000000000 --- a/application/libraries/MigrationLib.php +++ /dev/null @@ -1,466 +0,0 @@ -load->library('EPrintfLib'); - } - - /** - * Check if a column exists in a table and schema - */ - private function columnExists($name, $schema, $table) - { - $query = sprintf("SELECT %s FROM %s.%s LIMIT 1", $name, $schema, $table); - - if (@$this->db->simple_query($query)) - { - return true; - } - - return false; - } - - /** - * Print an info about the starting of method up - */ - protected function startUP() - { - $this->eprintflib->printInfo( - sprintf("%s Start method up of class %s %s", EPrintfLib::SEPARATOR, get_called_class(), EPrintfLib::SEPARATOR) - ); - } - - /** - * Print an info about the ending of method up - */ - protected function endUP() - { - $this->eprintflib->printInfo( - sprintf("%s End method up of class %s %s", EPrintfLib::SEPARATOR, get_called_class(), EPrintfLib::SEPARATOR) - ); - } - - /** - * Print an info about the starting of method down - */ - protected function startDown() - { - $this->eprintflib->printInfo( - sprintf("%s Start method down of class %s %s", EPrintfLib::SEPARATOR, get_called_class(), EPrintfLib::SEPARATOR) - ); - } - - /** - * Print an info about the ending of method down - */ - protected function endDown() - { - $this->eprintflib->printInfo( - sprintf("%s End method down of class %s %s", EPrintfLib::SEPARATOR, get_called_class(), EPrintfLib::SEPARATOR) - ); - } - - /** - * Adds a column, with attributes, to a table and schema - */ - protected function addColumn($schema, $table, $fields) - { - foreach ($fields as $name => $definition) - { - if (!$this->columnExists($name, $schema, $table)) - { - if ($this->dbforge->add_column($schema.'.'.$table, array($name => $definition))) - { - $this->eprintflib->printMessage(sprintf("Column %s.%s.%s of type %s added", $schema, $table, $name, $definition["type"])); - } - else - { - $this->eprintflib->printError(sprintf("Error while adding column %s.%s.%s of type %s", $schema, $table, $name, $definition["type"])); - } - } - else - { - $this->eprintflib->printInfo(sprintf("Column %s.%s.%s already exists", $schema, $table, $name)); - } - } - } - - /** - * Modifies a column, and its attributes, of a table and schema - */ - protected function modifyColumn($schema, $table, $fields) - { - foreach ($fields as $name => $definition) - { - if ($this->columnExists($name, $schema, $table)) - { - if ($this->dbforge->modify_column($schema.'.'.$table, array($name => $definition))) - { - $this->eprintflib->printMessage(sprintf("Column %s.%s.%s has been modified", $schema, $table, $name)); - } - else - { - $this->eprintflib->printError(sprintf("Error while modifying column %s.%s.%s", $schema, $table, $name)); - } - } - else - { - $this->eprintflib->printInfo(sprintf("Column %s.%s.%s doesn't exist", $schema, $table, $name)); - } - } - } - - /** - * Drops a column from a table and schema - */ - protected function dropColumn($schema, $table, $field) - { - if ($this->columnExists($field, $schema, $table)) - { - if ($this->dbforge->drop_column($schema.'.'.$table, $field)) - { - $this->eprintflib->printMessage(sprintf("Column %s.%s.%s has been dropped", $schema, $table, $field)); - } - else - { - $this->eprintflib->printError(sprintf("Error while dropping column %s.%s.%s", $schema, $table, $field)); - } - } - else - { - $this->eprintflib->printInfo(sprintf("Column %s.%s.%s doesn't exist", $schema, $table, $field)); - } - } - - /** - * Sets a column as primary key of a table and schema - */ - protected function addPrimaryKey($schema, $table, $name, $fields) - { - $stringFields = null; - - if (is_array($fields)) - { - if (count($fields) > 0) - { - $stringFields = ""; - for ($i = 0; $i < count($fields); $i++) - { - $stringFields .= $fields[$i]; - if ($i != count($fields) - 1) - { - $stringFields .= ", "; - } - } - $query = sprintf("ALTER TABLE %s.%s ADD CONSTRAINT %s PRIMARY KEY (%s)", $schema, $table, $name, $stringFields); - } - } - else - { - $query = sprintf("ALTER TABLE %s.%s ADD CONSTRAINT %s PRIMARY KEY (%s)", $schema, $table, $name, $fields); - } - - if (@$this->db->simple_query($query)) - { - $this->eprintflib->printMessage(sprintf("Added primary key %s on table %s.%s", $name, $schema, $table)); - } - else - { - $this->eprintflib->printError(sprintf("Adding primary key %s on table %s.%s", $name, $schema, $table)); - } - } - - /** - * Sets a column as foreign key of a table and schema - */ - protected function addForeingKey($schema, $table, $name, $field, $schemaDest, $tableDest, $fieldDest, $attributes) - { - $query = sprintf( - "ALTER TABLE %s.%s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s.%s (%s) %s", - $schema, - $table, - $name, - $field, - $schemaDest, - $tableDest, - $fieldDest, - $attributes - ); - - if (@$this->db->simple_query($query)) - { - $this->eprintflib->printMessage(sprintf("Added foreign key %s on table %s.%s", $name, $schema, $table)); - } - else - { - $this->eprintflib->printError(sprintf("Adding foreign key %s on table %s.%s", $name, $schema, $table)); - } - } - - /** - * Sets a column as unique key of a table and schema - */ - protected function addUniqueKey($schema, $table, $name, $fields) - { - $stringFields = null; - - if (is_array($fields)) - { - if (count($fields) > 0) - { - $stringFields = ""; - for ($i = 0; $i < count($fields); $i++) - { - $stringFields .= $fields[$i]; - if ($i != count($fields) - 1) - { - $stringFields .= ", "; - } - } - $query = sprintf("CREATE UNIQUE INDEX %s ON %s.%s (%s)", $name, $schema, $table, $stringFields); - } - } - else - { - $query = sprintf("CREATE UNIQUE INDEX %s ON %s.%s (%s)", $name, $schema, $table, $fields); - } - - if (@$this->db->simple_query($query)) - { - $this->eprintflib->printMessage(sprintf("Added unique key %s on table %s.%s", $name, $schema, $table)); - } - else - { - $this->eprintflib->printError(sprintf("Adding unique key %s on table %s.%s", $name, $schema, $table)); - } - } - - /** - * Grants permissions to a user on a table and schema - */ - protected function grantTable($permissions, $schema, $table, $user) - { - $stringPermission = null; - - if (is_array($permissions)) - { - if (count($permissions) > 0) - { - $stringPermission = ""; - for ($i = 0; $i < count($permissions); $i++) - { - $stringPermission .= $permissions[$i]; - if ($i != count($permissions) - 1) - { - $stringPermission .= ", "; - } - } - $query = sprintf("GRANT %s ON TABLE %s.%s TO %s", $stringPermission, $schema, $table, $user); - } - } - else - { - $query = sprintf("GRANT %s ON TABLE %s.%s TO %s", $permissions, $schema, $table, $user); - } - - if (@$this->db->simple_query($query)) - { - $this->eprintflib->printMessage( - sprintf( - "Granted permissions %s on table %s.%s to user %s", - is_null($stringPermission) ? $permissions : $stringPermission, - $schema, - $table, - $user - ) - ); - } - else - { - $this->eprintflib->printError( - sprintf( - "Granting permissions %s on table %s.%s to user %s", - is_null($stringPermission) ? $permissions : $stringPermission, - $schema, - $table, - $user - ) - ); - } - } - - /** - * Creates a table in a schema with columns - */ - protected function createTable($schema, $table, $fields) - { - $this->dbforge->add_field($fields); - - if ($this->dbforge->create_table($schema.'.'.$table, true)) - { - $this->eprintflib->printMessage(sprintf("Table %s.%s created or existing", $schema, $table)); - } - else - { - $this->eprintflib->printError(sprintf("Creating table %s.%s", $schema, $table)); - } - } - - /** - * Drops a table from a schema - */ - protected function dropTable($schema, $table) - { - if ($this->dbforge->drop_table($schema.".".$table)) - { - $this->eprintflib->printMessage(sprintf("Table %s.%s has been dropped", $schema, $table)); - } - else - { - $this->eprintflib->printError(sprintf("Dropping table %s.%s", $schema, $table)); - } - } - - /** - * Initializes a sequence with the max value of a column - */ - protected function initializeSequence($schemaSrc, $sequence, $schemaDst, $table, $field) - { - $query = sprintf("SELECT SETVAL('%s.%s', (SELECT MAX(%s) FROM %s.%s))", $schemaSrc, $sequence, $field, $schemaDst, $table); - - if (@$this->db->simple_query($query)) - { - $this->eprintflib->printMessage(sprintf("Sequence %s.%s has been initialized", $schemaSrc, $sequence)); - } - else - { - $this->eprintflib->printError(sprintf("Initializing sequence %s.%s", $schemaSrc, $sequence)); - } - } - - /** - * Add comment to a column - */ - protected function addCommentToColumn($schema, $table, $field, $comment) - { - $query = sprintf("COMMENT ON COLUMN %s.%s.%s IS ?", $schema, $table, $field); - - if (@$this->db->query($query, array($comment))) - { - $this->eprintflib->printMessage(sprintf("Comment added to %s.%s.%s", $schema, $table, $field)); - } - else - { - $this->eprintflib->printError(sprintf("Error while adding comment to %s.%s.%s", $schema, $table, $field)); - } - } - - /** - * Add comment to a table - */ - protected function addCommentToTable($schema, $table, $comment) - { - $query = sprintf("COMMENT ON TABLE %s.%s IS ?", $schema, $table, $field); - - if (@$this->db->query($query, array($comment))) - { - $this->eprintflib->printMessage(sprintf("Comment added to %s.%s", $schema, $table)); - } - else - { - $this->eprintflib->printError(sprintf("Error while adding comment to %s.%s", $schema, $table)); - } - } - /** - * Grants permissions to a user on a sequence - */ - protected function grantSequence($permissions, $schema, $sequence, $user) - { - $stringPermission = null; - - if (is_array($permissions)) - { - if (count($permissions) > 0) - { - $stringPermission = ""; - for ($i = 0; $i < count($permissions); $i++) - { - $stringPermission .= $permissions[$i]; - if ($i != count($permissions) - 1) - { - $stringPermission .= ", "; - } - } - $query = sprintf("GRANT %s ON SEQUENCE %s.%s TO %s", $stringPermission, $schema, $sequence, $user); - } - } - else - { - $query = sprintf("GRANT %s ON SEQUENCE %s.%s TO %s", $permissions, $schema, $sequence, $user); - } - - if (@$this->db->simple_query($query)) - { - $this->eprintflib->printMessage( - sprintf( - "Granted permissions %s on sequence %s.%s to user %s", - is_null($stringPermission) ? $permissions : $stringPermission, - $schema, - $sequence, - $user - ) - ); - } - else - { - $this->eprintflib->printError( - sprintf( - "Granting permissions %s on sequence %s.%s to user %s", - is_null($stringPermission) ? $permissions : $stringPermission, - $schema, - $sequence, - $user - ) - ); - } - } - - /** - * Executes the given query - */ - protected function execQuery($query) - { - if (! @$this->db->simple_query($query)) - { - $error = $this->db->error(); - - if (is_array($error) && isset($error["message"])) - { - $this->eprintflib->printError($error["message"]); - } - else - { - $this->eprintflib->printError("Error while executing a query"); - } - } - - $this->eprintflib->printInfo( - "Query correctly executed: ". - substr(preg_replace("/\s+/", " ", trim($query)), 0, EPrintfLib::PRINT_QUERY_LEN). - (strlen($query) > EPrintfLib::PRINT_QUERY_LEN ? "..." : "") - ); - } -} diff --git a/cis/private/profile/lva_liste.php b/cis/private/profile/lva_liste.php index 33eb7da3b..c4f54ce94 100644 --- a/cis/private/profile/lva_liste.php +++ b/cis/private/profile/lva_liste.php @@ -247,7 +247,14 @@ require_once('../../../include/benutzerberechtigung.class.php'); echo ''.$row->raumtypalternativ.''; echo ''.$row->stundenblockung.''; echo ''.$row->wochenrythmus.''; - echo ''.$row->semesterstunden.''; + if(getSprache()=='German') + { + echo ''.number_format($row->semesterstunden,2,$dec_point=",",$thousands_sep=".").''; + } + else + { + echo ''.number_format($row->semesterstunden,2,$dec_point=".",$thousands_sep=",").''; + } echo ''.$row->start_kw.''; $lvangebot->getAllFromLvId($row->lehrveranstaltung_id, $row->studiensemester_kurzbz); @@ -276,7 +283,7 @@ require_once('../../../include/benutzerberechtigung.class.php'); echo ' '; echo ' '; - + echo ' '; echo ' '; echo ' '; echo ' '; @@ -286,7 +293,14 @@ require_once('../../../include/benutzerberechtigung.class.php'); echo ' '; echo ' '; echo ''.$p->t('lvaliste/summe').''; - echo ''.number_format($summe_std,2).''; + if(getSprache()=='German') + { + echo ''.number_format($summe_std,2,$dec_point=",",$thousands_sep=".").''; + } + else + { + echo ''.number_format($summe_std,2,$dec_point=".",$thousands_sep=",").''; + } echo ' '; echo ''; echo ''; @@ -304,7 +318,7 @@ require_once('../../../include/benutzerberechtigung.class.php'); tbl_lehrveranstaltung.bezeichnung, tbl_projektarbeit.titel, (SELECT nachname || ' ' || vorname FROM public.tbl_benutzer JOIN public.tbl_person USING(person_id) WHERE uid=student_uid) as student, tbl_lehrveranstaltung.studiengang_kz, tbl_lehrveranstaltung.semester, - tbl_studiengang.email, tbl_betreuerart.beschreibung AS beutreuerart_beschreibung + tbl_studiengang.email, tbl_betreuerart.beschreibung AS beutreuerart_beschreibung, tbl_projektbetreuer.stunden FROM lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, lehre.tbl_projektarbeit, lehre.tbl_projektbetreuer, public.tbl_studiengang, lehre.tbl_betreuerart WHERE @@ -318,6 +332,7 @@ require_once('../../../include/benutzerberechtigung.class.php'); $stg_obj = new studiengang(); $stg_obj->getAll(null,null); + $summe_std = 0; if($result = $db->db_query($qry)) { @@ -329,6 +344,7 @@ require_once('../../../include/benutzerberechtigung.class.php'); echo ''; echo ''.$p->t('lvaliste/studiengang').''; echo ''.$p->t('lvaliste/semester').''; + echo ''.$p->t('lvaliste/stunden').''; echo ''.$p->t('lvaliste/lvBezeichnung').''; echo ''.$p->t('lvaliste/student').''; echo ''.$p->t('lvaliste/betreuungsart').''; @@ -339,13 +355,46 @@ require_once('../../../include/benutzerberechtigung.class.php'); echo ''; echo ''.$stg_obj->kuerzel_arr[$row->studiengang_kz].''; echo ''.$row->semester.''; + if(getSprache()=='German') + { + echo ''.number_format($row->stunden,2,$dec_point =",", $thousands_sep ="."). ''; + } + else + { + echo ''.number_format($row->stunden,2,$dec_point =".", $thousands_sep =","). ''; + } echo ''.$row->bezeichnung.''; echo ''.$row->student.''; echo ''.$row->beutreuerart_beschreibung.''; echo ''.$row->titel.''; - echo ''; + $summe_std+=$row->stunden; } + echo ''; + echo ''; + echo ''; + if(!defined('CIS_LVALISTE_NOTENEINGABE_ANZEIGEN') || CIS_LVALISTE_NOTENEINGABE_ANZEIGEN) + { + echo ' '; + } + if($lvinfo) + + echo ''.$p->t('lvaliste/summe').''; + + if(getSprache()=='German') + { + echo ''.number_format($summe_std,2,$dec_point=",",$thousands_sep=".").''; + } + else + { + echo ''.number_format($summe_std,2,$dec_point=".",$thousands_sep=",").''; + } + + + echo ' '; + + echo ''; + echo ''; } } @@ -426,6 +475,7 @@ require_once('../../../include/benutzerberechtigung.class.php'); echo ''; echo ''.$stg_obj->kuerzel_arr[$row->studiengang_kz].''; echo ''.$row->semester.''; + echo ''.$row->stunden.''; echo ''.$row->fachbereich_kurzbz.''; echo ''.$row->bezeichnung.''; echo ''.$lektoren.''; diff --git a/content/dragboard.js.php b/content/dragboard.js.php index 18a8d6186..2a96e0cda 100644 --- a/content/dragboard.js.php +++ b/content/dragboard.js.php @@ -116,7 +116,7 @@ var studentDDObserver= uid = tree.view.getCellText(v,col); if(uid=='') { - alert('Es koennen nur Personen mit UID (Studenten/Mitarbeiter) verschoben werden'); + alert('Es koennen nur Personen mit UID (Studierende/Mitarbeitende) verschoben werden'); return false; } paramList += ';'+uid; @@ -295,7 +295,7 @@ var LektorFunktionDDObserver= if(stg=='') { - alert('Mitarbeiter kann nur auf einen Studiengang gezogen werden'); + alert('MitarbeiterIn kann nur auf einen Studiengang gezogen werden'); return false; } diff --git a/content/fasoverlay.js.php b/content/fasoverlay.js.php index ffc83d977..9b3363d6d 100644 --- a/content/fasoverlay.js.php +++ b/content/fasoverlay.js.php @@ -147,7 +147,7 @@ function LektorFunktionDel() idx = tree.currentIndex; else { - alert('Bitte zuerst einen Mitarbeiter markieren'); + alert('Bitte zuerst eine/n MitarbeiterIn markieren'); return false; } @@ -223,7 +223,7 @@ function LektorFunktionMail() } } if(anzfault!=0) - alert(anzfault+' Mitarbeiter konnten nicht hinzugefuegt werden weil keine UID eingetragen ist!'); + alert(anzfault+' MitarbeiterInnen konnten nicht hinzugefuegt werden weil keine UID eingetragen ist!'); if(mailempfaenger!='') window.location.href=mailempfaenger; } @@ -891,7 +891,7 @@ function StatistikPrintLVPlanung() if(tree.currentIndex==-1) { - alert('Bitte zuerst einen Mitarbeiter auswaehlen'); + alert('Bitte zuerst eine/n MitarbeiterIn auswaehlen'); return; } @@ -905,7 +905,7 @@ function StatistikPrintLVPlanung() if(typeof(url)!='undefined') window.open(url,'LV-Planung'); else - alert('Bitte waehlen sie ein(en) Verband, Institut oder Lektor aus'); + alert('Bitte waehlen sie ein(e/en) Verband, Institut oder LektorIn aus'); } // **** @@ -956,7 +956,7 @@ function StatistikPrintLVPlanungExcel() if(tree.currentIndex==-1) { - alert('Bitte zuerst einen Mitarbeiter auswaehlen'); + alert('Bitte zuerst eine/n MitarbeiterIn auswaehlen'); return; } @@ -970,7 +970,7 @@ function StatistikPrintLVPlanungExcel() if(typeof(url)!='undefined') window.open(url,'LV-Planung'); else - alert('Bitte waehlen sie ein(en) Verband, Institut oder Lektor aus'); + alert('Bitte waehlen sie einen Verband, Institut oder LektorIn aus'); } // **** @@ -1134,14 +1134,14 @@ function StatistikPrintStudienverlaufStudent() //Wenn nichts markiert wurde -> alle exportieren if(tree.currentIndex==-1) { - alert("Bitte zuerst einen Studenten markieren"); + alert("Bitte zuerst eine/n Studierende/n markieren"); return; } var student_uid = getTreeCellText(tree, 'student-treecol-uid', tree.currentIndex); if (student_uid == '') { - alert('Markierte Person ist kein Student'); + alert('Markierte Person ist kein/e StudentIn'); return; } window.open('index.ci.php/person/gradelist/index/'+student_uid,'Studienverlauf'); @@ -1893,7 +1893,7 @@ function PrintStudienblatt(event) } catch(e) { - check = confirm('Achtung: Beim letzten (aktuellen) PreStudent-Status ist KEIN STUDIENPLAN eingetragen.\nDas Studienblatt ist moeglicherweise unvollstaendig.\nMoechten Sie es dennoch erstellen?'); + check = confirm('Achtung: Beim letzten (aktuellen) PreStudentInnen-Status ist KEIN STUDIENPLAN eingetragen.\nDas Studienblatt ist moeglicherweise unvollstaendig.\nMoechten Sie es dennoch erstellen?'); if (check == false) return false; } @@ -1906,7 +1906,7 @@ function PrintStudienblatt(event) if(studienplan_id=='') { - check = confirm('Achtung: Beim letzten (aktuellen) PreStudent-Status ist KEIN STUDIENPLAN eingetragen.\nDas Studienblatt ist moeglicherweise unvollstaendig.\nMoechten Sie es dennoch erstellen?'); + check = confirm('Achtung: Beim letzten (aktuellen) PreStudentInnen-Status ist KEIN STUDIENPLAN eingetragen.\nDas Studienblatt ist moeglicherweise unvollstaendig.\nMoechten Sie es dennoch erstellen?'); if (check == false) return false; } @@ -1969,7 +1969,7 @@ function PrintStudienblatt(event) } else { - alert('Bitte zuerst einen Studenten auswaehlen'); + alert('Bitte zuerst eine/n Studierende/n auswaehlen'); } } @@ -2001,7 +2001,7 @@ function PrintStudienblattEnglisch(event) } catch(e) { - check = confirm('Achtung: Beim letzten (aktuellen) PreStudent-Status ist KEIN STUDIENPLAN eingetragen.\nDas Studienblatt ist moeglicherweise unvollstaendig.\nMoechten Sie es dennoch erstellen?'); + check = confirm('Achtung: Beim letzten (aktuellen) PreStudentInnen-Status ist KEIN STUDIENPLAN eingetragen.\nDas Studienblatt ist moeglicherweise unvollstaendig.\nMoechten Sie es dennoch erstellen?'); if (check == false) return false; } @@ -2015,7 +2015,7 @@ function PrintStudienblattEnglisch(event) if(studienplan_id=='') { - check = confirm('Achtung: Beim letzten (aktuellen) PreStudent-Status ist KEIN STUDIENPLAN eingetragen.\nDas Studienblatt ist moeglicherweise unvollstaendig.\nMoechten Sie es dennoch erstellen?'); + check = confirm('Achtung: Beim letzten (aktuellen) PreStudentInnen-Status ist KEIN STUDIENPLAN eingetragen.\nDas Studienblatt ist moeglicherweise unvollstaendig.\nMoechten Sie es dennoch erstellen?'); if (check == false) return false; } @@ -2078,7 +2078,7 @@ function PrintStudienblattEnglisch(event) } else { - alert('Bitte zuerst einen Studenten auswaehlen'); + alert('Bitte zuerst eine/n Studierende/n auswaehlen'); } } diff --git a/content/fasoverlay.xul.php b/content/fasoverlay.xul.php index 88559cb10..8fef59273 100644 --- a/content/fasoverlay.xul.php +++ b/content/fasoverlay.xul.php @@ -228,14 +228,14 @@ echo ' - - + + - - + + diff --git a/content/funktionen.xul.php b/content/funktionen.xul.php index 0f487370a..9bbe10686 100644 --- a/content/funktionen.xul.php +++ b/content/funktionen.xul.php @@ -101,7 +101,7 @@ else class="sortDirectionIndicator" sort="rdf:http://www.technikum-wien.at/bnfunktion/rdf#uid"/> -