Compare commits

..

12 Commits

25 changed files with 1561 additions and 172 deletions
+20
View File
@@ -0,0 +1,20 @@
<?php
/**
* Configs for the Long Run Tasks
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
// Maximum LRTs for a single user in parallel
$config['lrt_max_number_single_user'] = 10;
// Maximum LRTs for the whole system in parallel
$config['lrt_max_number_system'] = 100;
// Maximum running time in hours for a single LRT before killing it
$config['lrt_max_run_timeout'] = 24;
// List of existing LRT types
$config['lrt_types'] = array('LRTDummy');
@@ -0,0 +1,112 @@
<?php
if (!defined("BASEPATH")) exit("No direct script access allowed");
/**
* - This controller acts as interface of the LongRunTaskLib that contains
* all the needed functionalities to operate with the Long Run Task system
* that is built on top of the Jobs Queue System
* - This is a Job Queue Worker that gets scheduled LRTs from the queue and executes them
* - Once all the LRTs have been started checks if there are LRTs that are running for too long and kills them
*/
class LongRunTaskExecJob extends JOB_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
// Changes the needed configs for LogLib
$this->LogLibJob->setConfigs(
array(
'dbExecuteUser' => get_class($this),
'requestId' => 'LRT'
)
);
// Loads LongRunTaskLib library
$this->load->library('LongRunTaskLib');
}
/**
* Executes all the new LRTs
*/
public function execEmAll()
{
$this->logInfo('Execute long run tasks started');
// Get all the LRTs that is possible to execute now
$lrtsResult = $this->longruntasklib->getNewLRTs();
// If an error occurred then return it
if (isError($lrtsResult)) return $lrtsResult;
if (hasData($lrtsResult))
{
// For each LRT
foreach (getData($lrtsResult) as $lrt)
{
// Execute the task
$executeLrtResult = $this->longruntasklib->executeLrt($lrt);
if (isError($executeLrtResult)) $this->logError($executeLrtResult);
}
}
$this->logInfo('Execute long run tasks ended');
}
/**
* Kills all the hanging LRTs
*/
public function killHangingLRTs()
{
$this->logInfo('Kill hanging LRTs started');
// Get all the LRTs that is possible to execute now
$lrtsResult = $this->longruntasklib->getHangingLRTs();
// If an error occurred then return it
if (isError($lrtsResult)) return $lrtsResult;
if (hasData($lrtsResult))
{
// For each LRT
foreach (getData($lrtsResult) as $lrt)
{
// Kill the task
$killLrtResult = $this->longruntasklib->killLrt($lrt);
if (isError($killLrtResult)) $this->logError($killLrtResult);
}
}
$this->logInfo('Kill hanging LRTs ended');
}
/**
*
*/
public function checkExecution()
{
$this->logInfo('Check execution long run tasks started');
// Get the related LRT data from the queue
$lrtsResult = $this->longruntasklib->getRunningLRTs();
// If an error occurred then return it
if (isError($lrtsResult)) return $lrtsResult;
// If there are running LRTs
if (hasData($lrtsResult))
{
// For each LRT
foreach (getData($lrtsResult) as $lrt)
{
// Check the LRT execution
$checkExecutionResult = $this->longruntasklib->checkExecution($lrt);
if (isError($checkExecutionResult)) $this->logError($checkExecutionResult);
}
}
$this->logInfo('Check execution long run tasks ended');
}
}
+82
View File
@@ -0,0 +1,82 @@
<?php
if (!defined("BASEPATH")) exit("No direct script access allowed");
/**
* Testing LRT to check if the LRT system is working properly
* This will be called by the LongRunTaskExecJob
*/
class LRTDummy extends LRT_Controller
{
/**
* This method must be implemented!
*/
public function run($jobid)
{
$this->logInfo('Long run tasks '.get_class($this).' started');
$this->_doIt($jobid);
$this->logInfo('Long run tasks '.get_class($this).' ended');
}
/**
* Loops on the number of seconds provided by the LRT input
* Sleeps every time 1 sec
* Writes the progress
* Writes the output
*/
private function _doIt($jobid)
{
// Get the LRT record related to the provided jobid
$lrtResult = $this->getLrt($jobid);
// If an error occurred or the record has not been found
if (isError($lrtResult))
{
$this->logError($lrtResult);
return;
}
if (!hasData($lrtResult))
{
$this->logError('LRT not found in database');
return;
}
// Get the record
$lrt = getData($lrtResult)[0];
// Get and check the input
$input = json_decode($lrt->{LongRunTaskLib::PROPERTY_INPUT});
if ($input == null)
{
$this->logError('LRT input is not a valid json');
return;
}
// Operation
for ($i = 0; $i < (int)$input->sleep; $i++)
{
sleep(1);
// Set the progress
$setProgressResult = $this->setProgress($jobid, (($i + 1) / (int)$input->sleep) * 100);
if (isError($setProgressResult))
{
$this->logError($setProgressResult);
return;
}
}
$sleepMsg = 'The user '.$lrt->{LongRunTaskLib::PROPERTY_UID}.' slept for '.$input->sleep.' seconds';
$this->logInfo($sleepMsg);
// Set the output
$setOutputResult = $this->setOutput($jobid, $sleepMsg);
if (isError($setOutputResult))
{
$this->logError($setOutputResult);
}
}
}
@@ -0,0 +1,56 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
use \stdClass as stdClass;
/**
*
*/
class LRTTest extends Auth_Controller
{
/**
*
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'system/developer:r',
'lrt1min' => 'system/developer:r',
)
);
// Loads LongRunTaskLib library
$this->load->library('LongRunTaskLib');
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Everything has a beginning
*/
public function index()
{
$this->load->view('system/lrtTest.php');
}
/**
*
*/
public function lrt1min()
{
$lrtInput = new stdClass();
$lrtInput->sleep = 1; // Sleep for 1 min
$this->outputJsonSuccess(
$this->longruntasklib->addNewLrtToQueue(
'LRTDummy', // LRT type
getAuthUID(), // UID executer
$lrtInput // LRT input
)
);
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
if (!defined("BASEPATH")) exit("No direct script access allowed");
/**
* Long Run Task
*
* - This controller acts as interface of the LongRunTaskLib that contains
* all the needed functionalities to operate with the Long Run Task system
* that is built on top of the Jobs Queue System
* - This is an abstract class that provide basic functionalities,
* it has to be extended to broaden its logic
* - Any implementation of a Long Run Task should extends this class to
* properly operate with the LRT system
*/
abstract class LRT_Controller extends JOB_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
// Changes the needed configs for LogLib
$this->LogLibJob->setConfigs(
array(
'dbExecuteUser' => get_class($this),
'requestId' => 'LRT'
)
);
// Loads LongRunTaskLib library
$this->load->library('LongRunTaskLib');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
abstract public function run($jobid);
//------------------------------------------------------------------------------------------------------------------
// Protected methods
/**
*
*/
protected function getLrt($jobid)
{
return $this->longruntasklib->getLrt($jobid);
}
/**
*
*/
protected function setProgress($jobid, $progress)
{
return $this->longruntasklib->setProgress($jobid, $progress);
}
/**
*
*/
protected function setOutput($jobid, $output)
{
return $this->longruntasklib->setOutuput($jobid, $output);
}
}
+81 -48
View File
@@ -2,6 +2,8 @@
if (!defined('BASEPATH')) exit('No direct script access allowed');
use \stdClass as stdClass;
/**
* Library that contains all the needed functionalities to operate with the Jobs Queue System
*/
@@ -24,12 +26,12 @@ class JobsQueueLib
const PROPERTY_END_TIME = 'endtime';
const PROPERTY_ERROR = 'error';
private $_ci; // CI instance
protected $_ci; // CI instance
/**
* Constructor
*/
public function __construct($authenticate = true)
public function __construct()
{
// Gets CI instance
$this->_ci =& get_instance();
@@ -62,14 +64,29 @@ class JobsQueueLib
*/
public function getOldestJobs($type, $maxAmount = null)
{
$this->_ci->JobsQueueModel->resetQuery();
$this->_ci->JobsQueueModel->addOrder('creationtime', 'ASC');
$types = $type; // default is array
$limit = 0; // default query limit
// If the maximum amount of jobs to retrieve have been specified
if (is_numeric($maxAmount)) $this->_ci->JobsQueueModel->addLimit($maxAmount);
if (is_numeric($maxAmount)) $limit = $maxAmount;
return $this->_ci->JobsQueueModel->loadWhere(array('status' => self::STATUS_NEW, 'type' => $type));
// If it is a string then include it into an array
if (!isEmptyString($type) && is_string($type)) $types = array($type);
// Return the result of the query
return $this->_ci->JobsQueueModel->execReadOnlyQuery('
SELECT jq.*
FROM system.tbl_jobsqueue jq
WHERE jq.type IN ?
AND jq.status = ?
ORDER BY jq.creationtime DESC
LIMIT ?',
array(
$types,
self::STATUS_NEW,
$limit
)
);
}
/**
@@ -77,11 +94,23 @@ class JobsQueueLib
*/
public function getJobsByTypeStatus($type, $status)
{
$this->_ci->JobsQueueModel->resetQuery();
$types = $type; // default is array
$this->_ci->JobsQueueModel->addOrder('creationtime', 'DESC');
// If it is a string then include it into an array
if (!isEmptyString($type) && is_string($type)) $types = array($type);
return $this->_ci->JobsQueueModel->loadWhere(array('status' => $status, 'type' => $type));
// Return the result of the query
return $this->_ci->JobsQueueModel->execReadOnlyQuery('
SELECT jq.*
FROM system.tbl_jobsqueue jq
WHERE jq.type IN ?
AND jq.status = ?
ORDER BY jq.creationtime DESC',
array(
$types,
$status
)
);
}
/**
@@ -253,8 +282,30 @@ class JobsQueueLib
return array($job);
}
//------------------------------------------------------------------------------------------------------------------
// Protected methods
/**
* Checks if the given job contains a valid type
*/
protected function _checkJobType($type, $types)
{
return $this->_inArray($type, $types, self::PROPERTY_TYPE);
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Drop not allowed properties from the given job
*/
private function _dropNotAllowedPropertiesNewJob(&$job)
{
unset($job->{self::PROPERTY_JOBID});
unset($job->{self::PROPERTY_CREATIONTIME});
unset($job->{self::PROPERTY_TYPE});
}
/**
* Checks the job object structure when needed for insert
@@ -281,34 +332,6 @@ class JobsQueueLib
return false; // better sorry than wrong
}
/**
* Checks the job object structure when needed for update
*/
private function _checkUpdateJobStructure(&$job)
{
// If job is a valid object
if (is_object($job) && property_exists($job, self::PROPERTY_JOBID)) return true; // it is valid!
// If not object then object it!
if (!is_object($job)) $job = new stdClass();
// If an error property was not already previously stored then store an error message in job object
if (!property_exists($job, self::PROPERTY_ERROR))
{
$job->{self::PROPERTY_ERROR} = 'The structure of the provided job is not valid';
}
return false; // better sorry than wrong
}
/**
* Checks if the given job contains a valid type
*/
private function _checkJobType($type, $types)
{
return $this->_inArray($type, $types, self::PROPERTY_TYPE);
}
/**
* Checks if the given job contains a valid status
*/
@@ -333,6 +356,26 @@ class JobsQueueLib
return $found;
}
/**
* Checks the job object structure when needed for update
*/
private function _checkUpdateJobStructure(&$job)
{
// If job is a valid object
if (is_object($job) && property_exists($job, self::PROPERTY_JOBID)) return true; // it is valid!
// If not object then object it!
if (!is_object($job)) $job = new stdClass();
// If an error property was not already previously stored then store an error message in job object
if (!property_exists($job, self::PROPERTY_ERROR))
{
$job->{self::PROPERTY_ERROR} = 'The structure of the provided job is not valid';
}
return false; // better sorry than wrong
}
/**
* Search in an array the given value
* The elements of the given array are objects
@@ -354,16 +397,6 @@ class JobsQueueLib
return $found;
}
/**
* Drop not allowed properties from the given job
*/
private function _dropNotAllowedPropertiesNewJob(&$job)
{
unset($job->{self::PROPERTY_JOBID});
unset($job->{self::PROPERTY_CREATIONTIME});
unset($job->{self::PROPERTY_TYPE});
}
/**
* Drop not allowed properties from the given job
*/
+333
View File
@@ -0,0 +1,333 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
require_once 'JobsQueueLib.php';
/**
* Library that contains all the needed functionalities to operate with the Long Run Tasks
*/
class LongRunTaskLib extends JobsQueueLib
{
// Config names
const CFG_LRT_MAX_NUMBER_SYSTEM = 'lrt_max_number_system';
const CFG_LRT_TYPES = 'lrt_types';
const CFG_LRT_MAX_RUN = 'lrt_max_run_timeout';
const CFG_LRT_MAX_NUMBER_USER = 'lrt_max_number_single_user';
// LRT object properties
const PROPERTY_UID = 'uid';
const PROPERTY_PID = 'pid';
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
// Loads the Long Run Tasks configs
$this->_ci->config->load('lrt');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods used by the LongRunTaskExecJob
/**
* Get the oldest added LRTs to the queue having status = new
* The maximum number of returned queued LRTs is limited by:
* number of currently running LRTs - maximum allowed number of LRTs for the system
*/
public function getNewLRTs()
{
// Get all the running LRTs
$runningLrtsResult = $this->getJobsByTypeStatus($this->_ci->config->item(self::CFG_LRT_TYPES), JobsQueueLib::STATUS_RUNNING);
if (isError($runningLrtsResult)) return $runningLrtsResult;
// The number of the currently running LRTs - the maximum LRTs for the system
$max_number_of_lrts = $this->_ci->config->item(self::CFG_LRT_MAX_NUMBER_SYSTEM) - count(getData($runningLrtsResult));
// Get the oldest LRTs added to the queue
return $this->getOldestJobs($this->_ci->config->item(self::CFG_LRT_TYPES), $max_number_of_lrts);
}
/**
* Get all the LRT that are running more then CFG_LRT_MAX_RUN hours
*/
public function getHangingLRTs()
{
// Return the result of the query
return $this->_ci->JobsQueueModel->execReadOnlyQuery('
SELECT jq.*
FROM system.tbl_jobsqueue jq
WHERE jq.type IN ?
AND jq.status = ?
AND jq.starttime < NOW() - INTERVAL \''.$this->_ci->config->item(self::CFG_LRT_MAX_RUN).' hours\'
ORDER BY jq.creationtime DESC',
array(
$this->_ci->config->item(self::CFG_LRT_TYPES),
JobsQueueLib::STATUS_RUNNING
)
);
}
/**
* Get all the LRT that are currently running
*/
public function getRunningLRTs()
{
// Return the result of the query
return $this->_ci->JobsQueueModel->execReadOnlyQuery('
SELECT jq.*
FROM system.tbl_jobsqueue jq
WHERE jq.type IN ?
AND jq.status = ?
ORDER BY jq.creationtime DESC',
array(
$this->_ci->config->item(self::CFG_LRT_TYPES),
JobsQueueLib::STATUS_RUNNING
)
);
}
/**
* Execute a LRT in background
* - Checks if the wanted LRT exists in the applcation/controllers/lrts directory
* - Then executes it in background via CI CLI
* - Stores the LRT pid into the database
*/
public function executeLrt($lrt)
{
$output = array();
// If does _not_ exist a LRT implementation for this LRT type, then return an error
if (!file_exists(APPPATH.'controllers/lrts/'.$lrt->{self::PROPERTY_TYPE}.'.php'))
{
return error('The required LRT implementation has not been found');
}
// Execute the LRT implementation (a CI controller from CLI) providing as parameter the jobid
exec(
// Command
sprintf(
'/usr/bin/php %s/../index.ci.php lrts/%s/run %s > /dev/null 2>&1 & echo $!',
APPPATH,
$lrt->{self::PROPERTY_TYPE},
$lrt->{self::PROPERTY_JOBID}
),
$output // Here goes the output from the standard output and error
);
// If a pid has not been returned
if (isEmptyArray($output) || !is_numeric($output[0])) return error('Not a valid pid has been returned');
// Set the pid, status and starttime of this LRT into the database
$updateLrtResult = $this->_ci->JobsQueueModel->update(
$lrt->{self::PROPERTY_JOBID},
array(
'pid' => $output[0],
'starttime' => 'NOW()',
'status' => self::STATUS_RUNNING
)
);
if (isError($updateLrtResult)) return $updateLrtResult;
}
/**
* Kill the provided LRT
* To avoid to kill a process that is not this LRT,
* since the same PID can be assigned to another process once this ended
*/
public function killLrt($lrt)
{
// Try to get the pid of this LRT from the system
$pid = exec(
sprintf(
'ps -eo pid,cmd | grep "index.ci.php lrts/%s/run %s" | grep -v grep | awk \'{print $1}\'',
$lrt->{self::PROPERTY_TYPE},
$lrt->{self::PROPERTY_JOBID}
)
);
// If the pid is the same then kill the process with a SIGKILL
if ($pid == $lrt->{self::PROPERTY_PID}) exec('kill -9 '.$lrt->{self::PROPERTY_PID}.' > /dev/null 2>&1');
// Set the LRT as failed in any case
$lrtExecFailedResult = $this->_ci->JobsQueueModel->update(
$lrt->{self::PROPERTY_JOBID},
array(
'endtime' => 'NOW()',
'status' => self::STATUS_FAILED
)
);
// If an error occurred then return it
if (isError($lrtExecFailedResult)) return $lrtExecFailedResult;
}
/**
*
*/
public function checkExecution($lrt)
{
// If the LRT stopped running
if (!$this->_isRunning($lrt))
{
// Loads MessageLib library
$this->_ci->load->library('MessageLib');
// Load the BenutzerModel
$this->_ci->load->model('person/Benutzer_model', 'BenutzerModel');
// Get the benutzer for this uid
$benutzerResult = $this->_ci->BenutzerModel->loadWhere(array('uid' => $lrt->{LongRunTaskLib::PROPERTY_UID}));
// If an error occurred then return it
if (isError($benutzerResult)) return $benutzerResult;
// If no benutzer has been found
if (!hasData($benutzerResult)) return error('No benutzer found, uid: '.$lrt->{LongRunTaskLib::PROPERTY_UID});
$benutzer = getData($benutzerResult)[0];
// Sends a message to the user
$messageResult = $this->_ci->messagelib->sendMessageUser(
$benutzer->person_id,
'Long run task ended',
'The long run task '.$lrt->{self::PROPERTY_TYPE}.' ended, output: '.$lrt->{self::PROPERTY_OUTPUT}
);
// If an error occurred then return it
if (isError($messageResult)) return $messageResult;
// Set the LRT as done
$lrtExecOverResult = $this->_ci->JobsQueueModel->update(
$lrt->{self::PROPERTY_JOBID},
array(
'endtime' => 'NOW()',
'status' => self::STATUS_DONE
)
);
// If an error occurred then return it
if (isError($lrtExecOverResult)) return $lrtExecOverResult;
}
}
//------------------------------------------------------------------------------------------------------------------
// Public methods used by the front end applications (standard controllers/end points, ex. controllers/system/LRTTest.php)
/**
* Add a single LRT to the queue
*/
public function addNewLrtToQueue($type, $uid, $lrtInput)
{
// Checks parameters
if (isEmptyString($type)) return error('The provided type parameter is not a valid string');
if (isEmptyString($uid)) return error('The provided uid parameter is not a valid string');
// Get all the running task for this uid
// Return the result of the query
$runningLRTbyUIDResult = $this->_ci->JobsQueueModel->execReadOnlyQuery('
SELECT jq.*
FROM system.tbl_jobsqueue jq
WHERE jq.status IN ?
AND jq.uid = ?
',
array(
array(
self::STATUS_NEW,
self::STATUS_RUNNING
),
$uid
)
);
// If an error occurred then return it
if (isError($runningLRTbyUIDResult)) return $runningLRTbyUIDResult;
// If the running tasks for this user are too many
if (count(getData($runningLRTbyUIDResult)) >= $this->_ci->config->item(self::CFG_LRT_MAX_NUMBER_USER))
{
return error('Too many running tasks for this user');
}
// Convert input to JSON and check it
$jsonLrtInput = json_encode($lrtInput);
if ($jsonLrtInput == null) return error('The provided LRT input is not valid');
// Get all the job types
$dbResult = $this->_ci->JobTypesModel->load();
if (isError($dbResult)) return $dbResult;
$types = getData($dbResult);
// If the given type is not present in database
if (!$this->_checkJobType($type, $types)) return error('The provided type parameter is not valid');
// Get all the job statuses
$dbResult = $this->_ci->JobStatusesModel->load();
if (isError($dbResult)) return $dbResult;
$statuses = getData($dbResult);
// Create an object that represent the new tbl_jobsqueue record with the provided input
$lrt = $this->generateJobs(self::STATUS_NEW, $jsonLrtInput)[0];
// What you asked is what you get!
$lrt->{self::PROPERTY_TYPE} = $type;
$lrt->{self::PROPERTY_UID} = $uid;
// Try to insert the single lrt into database
$dbNewLrtResult = $this->_ci->JobsQueueModel->insert($lrt);
// If an error occurred during while inserting in database
if (isError($dbNewLrtResult)) return $dbNewLrtResult;
return success('LRT added to the queue');
}
//------------------------------------------------------------------------------------------------------------------
// Public methods used by the LRT implementation (controllers/ltrs/*, ex. controllers/ltrs/LRTDummy)
/**
* Return a single record from the
*/
public function getLrt($jobid)
{
$this->_ci->JobsQueueModel->resetQuery();
return $this->_ci->JobsQueueModel->loadWhere(array('jobid' => $jobid));
}
/**
*
*/
public function setProgress($jobid, $progress)
{
return $this->_ci->JobsQueueModel->update($jobid, array('progress' => $progress));
}
/**
*
*/
public function setOutuput($jobid, $output)
{
return $this->_ci->JobsQueueModel->update($jobid, array('output' => json_encode($output)));
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Return true if the LRT is still running
*/
private function _isRunning($lrt)
{
// Try to get the pid of this LRT from the system
$pid = exec(
sprintf(
'ps -eo pid,cmd | grep "index.ci.php lrts/%s/run %s" | grep -v grep | awk \'{print $1}\'',
$lrt->{self::PROPERTY_TYPE},
$lrt->{self::PROPERTY_JOBID}
)
);
// If the pid is the same then the LRT is still running
return $pid == $lrt->{self::PROPERTY_PID};
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
$includesArray = array(
'title' => 'LRT Test Page',
'axios027' => true,
'bootstrap5' => true,
'fontawesome6' => true,
'vue3' => true,
'navigationcomponent' => true,
'phrases' => array(
'global',
'ui'
),
'customJSModules' => array('public/js/apps/LRTTest.js'),
);
$this->load->view('templates/FHC-Header', $includesArray);
?>
<div id="main">
<!-- Navigation component -->
<core-navigation-cmpt></core-navigation-cmpt>
<div id="content"></div>
</div>
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
@@ -0,0 +1,67 @@
<?php
$this->load->view('templates/header', array('title' => 'TemplateLinkDocuments', 'tablesort' => true, 'tableid' => 't1', 'sortList' => '2,1', 'headers' => '3:{sorter:false},4:{sorter:false}'));
?>
<script>
function addDocument(dokument_kurzbz)
{
var addDocumentDefault = document.getElementById("addDocumentDefault");
addDocumentDefault.selected = true;
$.post("../saveDocuments/"+<?=$vorlagestudiengang_id?>+"/"+dokument_kurzbz+"/0", function(answer)
{
window.location.href=window.location.href;
});
}
function delDocument(vorlagedokument_id)
{
$.post("../deleteDocumentLink/"+vorlagedokument_id, function(answer)
{
window.location.href=window.location.href;
});
}
function changeSort(vorlagedokument_id, sortnum)
{
$.post("../changeSort/"+vorlagedokument_id+"/"+sortnum, function(answer)
{
window.location.href=window.location.href;
});
}
</script>
<h2><?=$vorlagestudiengang_id?></h2>
<table id="t1" class="tablesorter">
<thead>
<tr>
<th>ID</th>
<th>Bezeichnung</th>
<th>Sortierung</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($documents as $d): ?>
<tr>
<td><?=$d->vorlagedokument_id?></td>
<td><?=$d->bezeichnung?></td>
<td> <?=$d->sort?></td>
<td><a onclick="changeSort('<?=$d->vorlagedokument_id?>', <?=$d->sort?>+1)"><img src="<?php echo APP_ROOT?>/skin/images/up.png"/></a> <a onclick="changeSort('<?=$d->vorlagedokument_id?>', <?=$d->sort?>-1)"><img src="<?php echo APP_ROOT?>/skin/images/down.png"/></a></td>
<td><a onclick="delDocument('<?=$d->vorlagedokument_id?>')">löschen</a></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<select>
<option selected="true" id="addDocumentDefault" disabled>Dokument hinzufuegen</option>
<?php foreach($allDocuments as $d): ?>
<option onclick="addDocument('<?=$d->dokument_kurzbz?>');"><?=$d->bezeichnung?></option>
<?php endforeach ;?>
</select>
</body>
</html>
@@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">
<html lang="de_AT">
<head>
<title>VileSci - Vorlage</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<frameset rows="30%,*">
<frame src="Vorlage/table" id="VorlageTop" name="VorlageTop" frameborder="0" />
<frame src="Vorlage/edit" id="VorlageBottom" name="VorlageBottom" frameborder="0" />
<noframes>
<body bgcolor="#FFFFFF">
This application works only with a frames-enabled browser.<br />
<a href="VorlageList">Use without frames</a>
</body>
</noframes>
</frameset>
</html>
@@ -0,0 +1,32 @@
<?php
$this->load->view('templates/header', array('title' => 'VorlageEdit', 'jsoneditor' => true));
?>
<div class="row">
<div class="span4">
<h2>Vorlage: <?php echo $vorlage->vorlage_kurzbz; ?></h2>
<form method="post" action="../save">
Bezeichnung: <input type="text" name="bezeichnung" value="<?php echo $vorlage->bezeichnung; ?>" />
Anmerkung: <input type="text" name="anmerkung" value="<?php echo $vorlage->anmerkung; ?>" /><br/>
MimeType:<?php echo $this->widgetlib->widget("mimetype_widget", array('mimetype' => $vorlage->mimetype)); ?>
Attribute: <?php echo $this->widgetlib->widget("jsoneditor_widget", array('json' => $vorlage->attribute)); ?>
<input type="hidden" name="attribute" id="attribute" value="<?=$vorlage->attribute?>" />
<input type="hidden" name="vorlage_kurzbz" value="<?php echo $vorlage->vorlage_kurzbz; ?>" />
<button type="submit" onclick="getJSON(this.form);">Save</button>
</form>
</div>
</div>
<script type="text/javascript" >
// get json
function getJSON(form)
{
form.elements["attribute"].value = JSON.stringify(jsoneditor.get(), null, 2);
//alert(form.elements["attribute"].value);
}
</script>
</body>
</html>
@@ -0,0 +1,38 @@
<?php
$this->load->view('templates/header', array('title' => 'VorlageList', 'tablesort' => true, 'tableid' => 't1', 'headers' => '4:{sorter:false}'));
?>
<div class="row">
<div class="span4">
<h2>Vorlagen</h2>
<form method="post" action="">
MimeType
<?php
// This is an example to show that you can load stuff from inside the template file
echo $this->widgetlib->widget("mimetype_widget", array('mimetype' => $mimetype));
?>
<button type="submit">Filter</button>
</form>
<table id="t1" class="tablesorter">
<thead>
<tr><th class='table-sortable:default'>Vorlage</th>
<th class='table-sortable:default'>Bezeichnung</th>
<th>Anmerkung</th><th>MimeType</th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($vorlage as $v): ?>
<tr><td><a href="edit/<?php echo $v->vorlage_kurzbz; ?>" target="VorlageBottom"><?php echo $v->vorlage_kurzbz; ?></a></td>
<td><?php echo $v->bezeichnung; ?></td>
<td><?php echo $v->anmerkung; ?></td>
<td><?php echo $v->mimetype; ?></td>
<td><a href="view/<?php echo $v->vorlage_kurzbz; ?>">Vorlagenexte bearbeiten</a></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
</div>
</div>
</body>
</html>
@@ -0,0 +1,50 @@
<?php
$this->load->view('templates/header', array('title' => 'VorlagetextList', 'tablesort' => true, 'tableid' => 't1', 'headers' => '7:{sorter:false},8:{sorter:false},9:{sorter:false}'));
?>
<div class="row">
<div class="span4">
<h2>Vorlagentext - <?php echo $vorlage_kurzbz; ?></h2>
<form method="post" action="../newText" target="VorlageBottom">
<input type="hidden" name="vorlage_kurzbz" value="<?php echo $vorlage_kurzbz; ?>"/>
<button type="submit">Neu</button>
</form>
<table id="t1" class="tablesorter">
<thead>
<tr>
<th>ID</th>
<th>Vorlage</th>
<th>Version</th>
<th>OrgEinheit</th>
<th>OrgForm</th>
<th>Berechtigung</th>
<th>Anmerkung</th>
<th>Aktiv</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($vorlagentext as $v): ?>
<tr>
<td><a href="../editText/<?php echo $v->vorlagestudiengang_id; ?>" target="VorlageBottom"><?php echo $v->vorlagestudiengang_id; ?></a></td>
<td><a href="../editText/<?php echo $v->vorlagestudiengang_id; ?>" target="VorlageBottom"><?php echo $v->vorlage_kurzbz; ?></a></td>
<td><?php echo $v->version; ?></td>
<td><?php echo $v->oe_kurzbz; ?></td>
<td></td>
<td><?php echo implode(',', $v->berechtigung); ?></td>
<td><?php echo $v->anmerkung_vorlagestudiengang; ?></td>
<td><?php echo $v->aktiv; ?></td>
<td><a href="../editText/<?php echo $v->vorlagestudiengang_id; ?>" target="VorlageBottom">Edit Text</a></td>
<td><a href="../linkDocuments/<?php echo $v->vorlagestudiengang_id; ?>" target="VorlageBottom">Edit Documents</a></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
</div>
</div>
<?php
$this->load->view('templates/footer');
?>
@@ -0,0 +1,3 @@
<?php
echo $text;
?>
+6
View File
@@ -13,6 +13,7 @@ isset($title) ? $title = 'VileSci - '.$title : $title = 'VileSci';
!isset($headers) ? $headers = '' : $headers = $headers;
!isset($tinymce) ? $tinymce = false : $tinymce = $tinymce;
!isset($jsoneditor) ? $jsoneditor = false : $jsoneditor = $jsoneditor;
!isset($jsonforms) ? $jsonforms = false : $jsonforms = $jsonforms;
!isset($textile) ? $textile = false : $textile = $textile;
!isset($widgetsCSS) ? $widgetsCSS = false : $widgetsCSS = $widgetsCSS;
!isset($datepicker) ? $datepicker = false : $datepicker = $datepicker;
@@ -106,6 +107,11 @@ if($jqueryV1 && $jqueryV2) show_error("Two JQuery versions used: composer and in
<script type="text/javascript" src="<?php echo base_url('vendor/josdejong/jsoneditor/dist/jsoneditor.js');?>"></script>
<?php endif ?>
<?php if($jsonforms) : ?>
<link rel="stylesheet" type="text/css" href="<?php echo base_url('vendor/brutusin/json-forms/dist/css/brutusin-json-forms.min.css'); ?>" />
<script type="text/javascript" src="<?php echo base_url('vendor/brutusin/json-forms/dist/js/brutusin-json-forms.min.js'); ?>"></script>
<?php endif ?>
<?php if($widgetsCSS) : ?>
<link rel="stylesheet" type="text/css" href="<?php echo base_url('skin/widgets.css'); ?>" />
<?php endif ?>
+10
View File
@@ -0,0 +1,10 @@
<div id="<?=$id?>" style="<?=$style?>"></div>
<script language="Javascript" type="text/javascript">
var container = document.getElementById('<?=$id?>');
var schema = <?=$schema?>;
var BrutusinForms = brutusin["json-forms"];
var <?=$objectname?> = BrutusinForms.create(schema);
<?=$objectname?>.render(container);
</script>
+47
View File
@@ -0,0 +1,47 @@
<?php
/*
* JSON-Forms widget
*/
class jsonforms_widget extends Widget
{
public function display($data)
{
// set default values if needed
if (! isset($data['objectname']))
$data['objectname'] = 'bf';
if (! isset($data['id']))
$data['id'] = 'jsonforms';
if (! isset($data['style']))
$data['style'] = 'width: 50%; ';
if (! isset($data['schema']))
$data['schema'] = '{
"$schema": "http://json-schema.org/draft-03/schema#",
"title": "Person",
"type": "object",
"properties": {
"anrede": {
"type": "string",
"enum": [
"Herr",
"Frau"
],
"default": "Herr"
},
"vorname": {
"type": "string",
"description": "Firstname",
"minLength": 2,
"default": "Vorname"
},
"nachname": {
"type": "string",
"description": "Surename",
"minLength": 2,
"default": "Nachname"
}
}
}';
$this->view('widgets/jsonforms', $data);
}
}
+14
View File
@@ -172,6 +172,17 @@
}
}
},
{
"type": "package",
"package": {
"name": "brutusin/json-forms",
"version": "1.4.0",
"dist": {
"url": "https://github.com/brutusin/json-forms/archive/v1.4.0.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
@@ -468,8 +479,11 @@
"jquery/jquery2": "2.*",
"jquery/sizzle": "1.0.*",
"jquery-archive/jquery-metadata": "1.0.*",
"brutusin/json-forms": "1.4.0",
"josdejong/jsoneditor": "5.5.6",
"kingsquare/json-schema-form": "*",
"ludo/jquery-treetable": "3.2.0",
"michelf/php-markdown": "1.5.0",
Generated
+296 -123
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "146d2d3708e44cf5966be727e54c0a48",
"content-hash": "869cbc35bd1ba90ab90934fcb41b0f51",
"packages": [
{
"name": "afarkas/html5shiv",
@@ -77,6 +77,15 @@
},
"type": "library"
},
{
"name": "brutusin/json-forms",
"version": "1.4.0",
"dist": {
"type": "zip",
"url": "https://github.com/brutusin/json-forms/archive/v1.4.0.zip"
},
"type": "library"
},
{
"name": "chillerlan/php-qrcode",
"version": "2.0.8",
@@ -888,12 +897,12 @@
"version": "v6.0.0",
"source": {
"type": "git",
"url": "https://github.com/googleapis/php-jwt.git",
"url": "https://github.com/firebase/php-jwt.git",
"reference": "0541cba75ab108ef901985e68055a92646c73534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/php-jwt/zipball/0541cba75ab108ef901985e68055a92646c73534",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/0541cba75ab108ef901985e68055a92646c73534",
"reference": "0541cba75ab108ef901985e68055a92646c73534",
"shasum": ""
},
@@ -935,8 +944,8 @@
"php"
],
"support": {
"issues": "https://github.com/googleapis/php-jwt/issues",
"source": "https://github.com/googleapis/php-jwt/tree/v6.0.0"
"issues": "https://github.com/firebase/php-jwt/issues",
"source": "https://github.com/firebase/php-jwt/tree/v6.0.0"
},
"time": "2022-01-24T15:18:34+00:00"
},
@@ -1077,6 +1086,115 @@
},
"type": "library"
},
{
"name": "justinrainbow/json-schema",
"version": "1.3.7",
"source": {
"type": "git",
"url": "https://github.com/jsonrainbow/json-schema.git",
"reference": "87b54b460febed69726c781ab67462084e97a105"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/87b54b460febed69726c781ab67462084e97a105",
"reference": "87b54b460febed69726c781ab67462084e97a105",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"json-schema/json-schema-test-suite": "1.1.0",
"phpdocumentor/phpdocumentor": "~2",
"phpunit/phpunit": "~3.7"
},
"bin": [
"bin/validate-json"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"psr-0": {
"JsonSchema": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Bruno Prieto Reis",
"email": "bruno.p.reis@gmail.com"
},
{
"name": "Justin Rainbow",
"email": "justin.rainbow@gmail.com"
},
{
"name": "Igor Wiedler",
"email": "igor@wiedler.ch"
},
{
"name": "Robert Schönthal",
"email": "seroscho@googlemail.com"
}
],
"description": "A library to validate a json schema.",
"homepage": "https://github.com/justinrainbow/json-schema",
"keywords": [
"json",
"schema"
],
"support": {
"issues": "https://github.com/jsonrainbow/json-schema/issues",
"source": "https://github.com/jsonrainbow/json-schema/tree/1.3.7"
},
"time": "2014-08-25T02:48:14+00:00"
},
{
"name": "kingsquare/json-schema-form",
"version": "0.6",
"source": {
"type": "git",
"url": "https://github.com/kingsquare/json-schema-form.git",
"reference": "609049fab463e0b7d6d2a2b315e0f58172333b89"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kingsquare/json-schema-form/zipball/609049fab463e0b7d6d2a2b315e0f58172333b89",
"reference": "609049fab463e0b7d6d2a2b315e0f58172333b89",
"shasum": ""
},
"require": {
"justinrainbow/json-schema": "1.3.*",
"twig/twig": "1.*"
},
"type": "library",
"autoload": {
"psr-0": {
"JsonSchemaForm": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"authors": [
{
"name": "Kingsquare",
"email": "json-schema-form@kingsquare.nl"
}
],
"description": "A framework-agnostic PHP Implementation for generating simple forms based on json-schema",
"support": {
"issues": "https://github.com/kingsquare/json-schema-form/issues",
"source": "https://github.com/kingsquare/json-schema-form/tree/master"
},
"abandoned": true,
"time": "2014-07-10T12:27:19+00:00"
},
{
"name": "ludo/jquery-treetable",
"version": "3.2.0",
@@ -1498,16 +1616,16 @@
},
{
"name": "phpseclib/phpseclib",
"version": "2.0.55",
"version": "2.0.48",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "d73c9e019a895be83b18a2ccccfa7e2b0a648743"
"reference": "eaa7be704b8b93a6913b69eb7f645a59d7731b61"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d73c9e019a895be83b18a2ccccfa7e2b0a648743",
"reference": "d73c9e019a895be83b18a2ccccfa7e2b0a648743",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/eaa7be704b8b93a6913b69eb7f645a59d7731b61",
"reference": "eaa7be704b8b93a6913b69eb7f645a59d7731b61",
"shasum": ""
},
"require": {
@@ -1515,7 +1633,7 @@
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0|^8.5|^9.4",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4",
"squizlabs/php_codesniffer": "~2.0"
},
"suggest": {
@@ -1588,7 +1706,7 @@
],
"support": {
"issues": "https://github.com/phpseclib/phpseclib/issues",
"source": "https://github.com/phpseclib/phpseclib/tree/2.0.55"
"source": "https://github.com/phpseclib/phpseclib/tree/2.0.48"
},
"funding": [
{
@@ -1604,7 +1722,7 @@
"type": "tidelift"
}
],
"time": "2026-06-14T19:53:12+00:00"
"time": "2024-12-14T21:03:54+00:00"
},
{
"name": "rmariuzzo/jquery-checkboxes",
@@ -1624,6 +1742,85 @@
},
"type": "library"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.19.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b",
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
},
"branch-alias": {
"dev-main": "1.19-dev"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-10-23T09:01:57+00:00"
},
{
"name": "tapmodo/jcrop",
"version": "2.0.4",
@@ -1670,6 +1867,74 @@
},
"type": "library"
},
{
"name": "twig/twig",
"version": "v1.42.5",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e",
"reference": "87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e",
"shasum": ""
},
"require": {
"php": ">=5.5.0",
"symfony/polyfill-ctype": "^1.8"
},
"require-dev": {
"psr/container": "^1.0",
"symfony/phpunit-bridge": "^4.4|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.42-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
},
"psr-4": {
"Twig\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Twig Team",
"role": "Contributors"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "https://twig.symfony.com",
"keywords": [
"templating"
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/1.x"
},
"time": "2020-02-11T05:59:23+00:00"
},
{
"name": "vuejs/vuedatepicker_css",
"version": "7.2.0",
@@ -2461,29 +2726,33 @@
},
{
"name": "phpmetrics/phpmetrics",
"version": "v2.9.1",
"version": "v2.8.2",
"source": {
"type": "git",
"url": "https://github.com/phpmetrics/PhpMetrics.git",
"reference": "e2e68ddd1543bc3f44402c383f7bccb62de1ece3"
"reference": "4b77140a11452e63c7a9b98e0648320bf6710090"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpmetrics/PhpMetrics/zipball/e2e68ddd1543bc3f44402c383f7bccb62de1ece3",
"reference": "e2e68ddd1543bc3f44402c383f7bccb62de1ece3",
"url": "https://api.github.com/repos/phpmetrics/PhpMetrics/zipball/4b77140a11452e63c7a9b98e0648320bf6710090",
"reference": "4b77140a11452e63c7a9b98e0648320bf6710090",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"nikic/php-parser": "^3|^4|^5"
"nikic/php-parser": "^3|^4",
"php": ">=5.5"
},
"replace": {
"halleck45/php-metrics": "*",
"halleck45/phpmetrics": "*"
},
"require-dev": {
"phpunit/phpunit": "*"
"phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14",
"sebastian/comparator": ">=1.2.3",
"squizlabs/php_codesniffer": "^3.5",
"symfony/dom-crawler": "^3.0 || ^4.0 || ^5.0"
},
"bin": [
"bin/phpmetrics"
@@ -2519,15 +2788,9 @@
],
"support": {
"issues": "https://github.com/PhpMetrics/PhpMetrics/issues",
"source": "https://github.com/phpmetrics/PhpMetrics/tree/v2.9.1"
"source": "https://github.com/phpmetrics/PhpMetrics/tree/v2.8.2"
},
"funding": [
{
"url": "https://github.com/Halleck45",
"type": "github"
}
],
"time": "2025-09-25T05:21:02+00:00"
"time": "2023-03-08T15:03:36+00:00"
},
{
"name": "phpspec/prophecy",
@@ -2864,6 +3127,7 @@
"issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
"source": "https://github.com/sebastianbergmann/php-token-stream/tree/master"
},
"abandoned": true,
"time": "2017-11-27T05:48:46+00:00"
},
{
@@ -3699,16 +3963,16 @@
},
{
"name": "sebastian/recursion-context",
"version": "3.0.3",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "8fe7e75986a9d24b4cceae847314035df7703a5a"
"reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/8fe7e75986a9d24b4cceae847314035df7703a5a",
"reference": "8fe7e75986a9d24b4cceae847314035df7703a5a",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/9bfd3c6f1f08c026f542032dfb42813544f7d64c",
"reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c",
"shasum": ""
},
"require": {
@@ -3750,27 +4014,15 @@
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.3"
"source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
"type": "tidelift"
}
],
"time": "2025-08-10T05:25:53+00:00"
"time": "2024-03-01T14:07:30+00:00"
},
{
"name": "sebastian/resource-operations",
@@ -4370,85 +4622,6 @@
],
"time": "2020-11-16T17:02:08+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.19.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b",
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
},
"branch-alias": {
"dev-main": "1.19-dev"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-10-23T09:01:57+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.19.0",
+1
View File
@@ -225,6 +225,7 @@ $menu=array
'name'=>'Admin', 'opener'=>'true', 'hide'=>'true', 'permissions'=>array('basis/cronjob'), 'image'=>'vilesci_admin.png',
'link'=>'left.php?categorie=Admin', 'target'=>'nav',
'Cronjobs'=>array('name'=>'Cronjobs', 'link'=>'stammdaten/cronjobverwaltung.php', 'target'=>'main','permissions'=>array('basis/cronjob')),
'Vorlagen'=>array('name'=>'Vorlagen', 'link'=>'../index.ci.php/system/Vorlage', 'target'=>'main','permissions'=>array('basis/cronjob')),
'Phrasen'=>array('name'=>'Phrasen', 'link'=>'../index.ci.php/system/Phrases', 'target'=>'main','permissions'=>array('basis/cronjob'))
)
);
+9
View File
@@ -0,0 +1,9 @@
export default {
addNew1MinLrt()
{
return {
method: 'post',
url: '/system/LRTTest/lrt1min'
};
},
}
+48
View File
@@ -0,0 +1,48 @@
/**
* Copyright (C) 2022 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import PluginsPhrasen from '../plugins/Phrasen.js';
import {CoreNavigationCmpt} from '../components/navigation/Navigation.js'
import ApiLrt from "../api/LRTTEst.js";
const lrtTestApp = Vue.createApp({
data: function() {
return {
};
},
components: {
CoreNavigationCmpt,
},
methods: {
addNew1MinLrt() {
this.$api.call(ApiLrt.addNew1MinLrt())
.then(result => {
this.dropdowns.studiensemester_array = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
}
},
template: `
<button type="button" class="btn btn-primary" @click="addNew1MinLrt()">Add a 1 min LRT</button>
`
});
FhcApps.makeExtendable(lrtTestApp);
lrtTestApp.use(PluginsPhrasen).mount('#main');
+2 -1
View File
@@ -94,6 +94,7 @@ require_once('dbupdate_3.4/71399_dashboard_update_widget_paths.php');
require_once('dbupdate_3.4/71645_studvw_messagetab_ladezeit.php');
require_once('dbupdate_3.4/71566_studienordnungsdokument_neuer_organisationseinheitstyp_programm.php');
require_once('dbupdate_3.4/70376_lohnguide.php');
require_once('dbupdate_3.4/76203_Asynchrone_Tasks.php');
require_once('dbupdate_3.4/75888_reihungstest_mehrfachdurchfuehrung.php');
require_once('dbupdate_3.4/76150_perm_other_lv_plan.php');
require_once('dbupdate_3.4/68957_dashboard_bookmark_neue_Spalte_sort.php');
@@ -433,7 +434,7 @@ $tabellen=array(
"system.tbl_log" => array("log_id","person_id","zeitpunkt","app","oe_kurzbz","logtype_kurzbz","logdata","insertvon","taetigkeit_kurzbz"),
"system.tbl_logtype" => array("logtype_kurzbz", "data_schema"),
"system.tbl_filters" => array("filter_id","app","dataset_name","filter_kurzbz","person_id","description","sort","default_filter","filter","oe_kurzbz","statistik_kurzbz"),
"system.tbl_jobsqueue" => array("jobid", "type", "creationtime", "status", "input", "output", "starttime", "endtime", "insertvon", "insertamum"),
"system.tbl_jobsqueue" => array("jobid", "type", "creationtime", "status", "input", "output", "starttime", "endtime", "insertvon", "insertamum", "pid", "uid", "progress"),
"system.tbl_jobstatuses" => array("status"),
"system.tbl_jobtriggers" => array("type", "status", "following_type"),
"system.tbl_jobtypes" => array("type", "description"),
@@ -0,0 +1,59 @@
<?php
// Add column pid to system.tbl_jobsqueue
if (!$result = @$db->db_query('SELECT "pid" FROM "system"."tbl_jobsqueue" LIMIT 1'))
{
$qry = 'ALTER TABLE "system"."tbl_jobsqueue" ADD "pid" INT NULL DEFAULT NULL;';
if (!$db->db_query($qry))
echo '<strong>system.tbl_jobsqueue: '.$db->db_last_error().'</strong><br>';
else
echo '<br>Added column pid to table system.tbl_jobsqueue';
}
// Add column uid to system.tbl_jobsqueue
if (!$result = @$db->db_query('SELECT "uid" FROM "system"."tbl_jobsqueue" LIMIT 1'))
{
$qry = 'ALTER TABLE "system"."tbl_jobsqueue" ADD "uid" VARCHAR(32) NULL DEFAULT NULL;';
if (!$db->db_query($qry))
echo '<strong>system.tbl_jobsqueue: '.$db->db_last_error().'</strong><br>';
else
echo '<br>Added column uid to table system.tbl_jobsqueue';
}
// Add column progress to system.tbl_jobsqueue
if (!$result = @$db->db_query('SELECT "progress" FROM "system"."tbl_jobsqueue" LIMIT 1'))
{
$qry = 'ALTER TABLE "system"."tbl_jobsqueue" ADD "progress" NUMERIC(2,1) NULL DEFAULT 0;';
if (!$db->db_query($qry))
echo '<strong>system.tbl_jobsqueue: '.$db->db_last_error().'</strong><br>';
else
echo '<br>Added column progress to table system.tbl_jobsqueue';
}
// Add foreign key fk_jobsqueue_benutzer_uid on system.tbl_jobsqueue.uid with public.tbl_benutzer.uid
if ($result = $db->db_query("SELECT conname FROM pg_constraint WHERE conname = 'fk_jobsqueue_benutzer_uid'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = 'ALTER TABLE "system"."tbl_jobsqueue" ADD CONSTRAINT "fk_jobsqueue_benutzer_uid" FOREIGN KEY ("uid") REFERENCES "public"."tbl_benutzer" ("uid") ON DELETE RESTRICT ON UPDATE CASCADE;';
if (!$db->db_query($qry))
echo '<strong>system.tbl_jobsqueue: '.$db->db_last_error().'</strong><br>';
else
echo '<br>Created foreign key fk_jobsqueue_benutzer_uid';
}
}
// Add new webservice type in system.tbl_webservicetyp
if ($result = @$db->db_query("SELECT 1 FROM system.tbl_webservicetyp WHERE webservicetyp_kurzbz = 'lrt';"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "INSERT INTO system.tbl_webservicetyp(webservicetyp_kurzbz, beschreibung) VALUES('lrt', 'Long Run Task');";
if (!$db->db_query($qry))
echo '<strong>system.tbl_webservicetyp '.$db->db_last_error().'</strong><br>';
else
echo ' system.tbl_webservicetyp: Added webservice type "lrt"<br>';
}
}
+78
View File
@@ -1638,6 +1638,84 @@ $filters = array(
}',
'oe_kurzbz' => null,
),
array(
'app' => 'core',
'dataset_name' => 'logs',
'filter_kurzbz' => 'lrts24hours',
'description' => '{Last 24 hours LRTs logs}',
'sort' => 2,
'default_filter' => false,
'filter' => '
{
"name": "All Long Run Tasks logs from the last 24 hours",
"columns": [
{"name": "RequestId"},
{"name": "ExecutionTime"},
{"name": "ExecutedBy"},
{"name": "Description"},
{"name": "Data"}
],
"filters": [
{
"name": "WebserviceType",
"operation": "contains",
"condition": "job"
},
{
"name": "RequestId",
"operation": "contains",
"condition": "LRT"
},
{
"name": "ExecutionTime",
"operation": "lt",
"condition": "24",
"option": "hours"
}
]
}
',
'oe_kurzbz' => null,
),
array(
'app' => 'core',
'dataset_name' => 'logs',
'filter_kurzbz' => 'lrts48hours',
'description' => '{Last 48 hours LRTs logs}',
'sort' => 2,
'default_filter' => false,
'filter' => '
{
"name": "All Long Run Tasks logs from the last 48 hours",
"columns": [
{"name": "RequestId"},
{"name": "ExecutionTime"},
{"name": "ExecutedBy"},
{"name": "Description"},
{"name": "Data"}
],
"filters": [
{
"name": "WebserviceType",
"operation": "contains",
"condition": "job"
},
{
"name": "RequestId",
"operation": "contains",
"condition": "LRT"
},
{
"name": "ExecutionTime",
"operation": "lt",
"condition": "48",
"option": "hours"
}
]
}
',
'oe_kurzbz' => null,
),
);
// Loop through the filters array