/** * @param $problem \Problem */ public static function hideProblemAndItsAssignments($problem) { $problem->setDeleted(true); Repositories::persist($problem); foreach ($problem->getAssignments() as $assignment) { $assignment->setDeleted(true); Repositories::getEntityManager()->persist($assignment); } Repositories::flushAll(); }
protected function body() { if (!$this->userHasPrivileges()) { return; } $query = "SELECT a, p, l, z, g FROM Assignment a JOIN a.problem p LEFT JOIN p.plugin z JOIN p.lecture l JOIN a.group g WITH g.id IN (SELECT IDENTITY(k.group) FROM \\Subscription k WHERE k.user = :id AND a.deleted = false)"; /** * @var $assignments \Assignment[] */ $userId = User::instance()->getId(); $assignments = Repositories::getEntityManager()->createQuery($query)->setParameter('id', $userId)->getResult(); foreach ($assignments as $assignment) { $submissionGraded = count(Repositories::getRepository(Repositories::Submission)->findBy(['assignment' => $assignment->getId(), 'user' => $userId, 'status' => \Submission::STATUS_GRADED])) > 0; $submissionExists = count(Repositories::getRepository(Repositories::Submission)->findBy(['assignment' => $assignment->getId(), 'user' => $userId])) > 0; $row = [$assignment->getId(), $assignment->getProblem()->getName(), $assignment->getProblem()->getDescription(), $assignment->getProblem()->getPlugin() ? $assignment->getProblem()->getPlugin()->getDescription() : Language::get(StringID::NoPluginUsed), $assignment->getDeadline()->format("Y-m-d H:i:s"), $assignment->getReward(), $assignment->getProblem()->getLecture()->getName(), $assignment->getProblem()->getLecture()->getDescription(), $assignment->getGroup()->getName(), $assignment->getGroup()->getDescription(), $submissionExists, $submissionGraded]; $this->addRowToOutput($row); } }
<?php require_once __DIR__ . "/../../vendor/autoload.php"; \asm\core\Config::init(__DIR__ . "/../config.ini", __DIR__ . "/../internal.ini"); return \Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet(\asm\core\Repositories::getEntityManager());
/** * Launches plugin and updates database with results. * @param string $pluginType one of 'php', 'java', or 'exe' * @param string $pluginFile plugin file path * @param string $inputFile input file path * @param boolean $isTest is this a plugin test or a submission? true if plugin test * @param int $rowId ID of row to be updated * @param array $arguments plugin arguments * @return bool true if no error occurred */ public static function launchPlugin($pluginType, $pluginFile, $inputFile, $isTest, $rowId, $arguments = array()) { try { $response = null; if (!is_file($pluginFile) || !is_file($inputFile)) { $error = "plugin file and/or input file don't exist"; } else { array_unshift($arguments, $inputFile); $cwd = getcwd(); chdir(dirname($pluginFile)); switch ($pluginType) { case 'php': $launcher = new PhpLauncher(); ob_start(); $error = $launcher->launch($pluginFile, $arguments, $response); ob_end_clean(); break; case 'java': $launcher = new JavaLauncher(); $error = $launcher->launch($pluginFile, $arguments, $responseString); break; case 'exe': $launcher = new ExeLauncher(); $error = $launcher->launch($pluginFile, $arguments, $responseString); break; default: $error = "unsupported plugin type '{$pluginType}'"; } chdir($cwd); } if (!$error) { if (isset($responseString)) { try { $response = PluginResponse::fromXmlString($responseString); } catch (Exception $ex) { $response = PluginResponse::createError('Internal error. Plugin did not supply valid response XML and this error occurred: ' . $ex->getMessage() . '. Plugin instead supplied this response string: ' . $responseString); } } } else { $response = PluginResponse::createError('Plugin cannot be launched (' . $error . ').'); } $outputFile = $response->getOutput(); if ($outputFile) { $outputFolder = Config::get('paths', 'output'); $newFile = $outputFolder . date('Y-m-d_H-i-s_') . StringUtils::randomString(10) . '.zip'; if (rename($outputFile, $newFile)) { $outputFile = $newFile; } else { $outputFile = 'tmp-file-rename-failed'; } } /** * @var $pluginTest \PluginTest * @var $submission \Submission * @var $previousSubmissions \Submission[] */ if ($isTest) { $pluginTest = Repositories::findEntity(Repositories::PluginTest, $rowId); $pluginTest->setStatus(\PluginTest::STATUS_COMPLETED); $pluginTest->setSuccess($response->getFulfillment()); $pluginTest->setInfo($response->getDetails()); $pluginTest->setOutput($outputFile); Repositories::persistAndFlush($pluginTest); } else { $submission = Repositories::findEntity(Repositories::Submission, $rowId); // There is a sort of a race condition in here. // It is, in theory, possible, that there will be two submissions with the "latest" status after all is done // This should not happen in practice, though, and even if it does, it will have negligible negative effects. $previousSubmissions = Repositories::makeDqlQuery("SELECT s FROM \\Submission s WHERE s.user = :sameUser AND s.assignment = :sameAssignment AND s.status != 'graded' AND s.status != 'deleted'")->setParameter('sameUser', $submission->getUser()->getId())->setParameter('sameAssignment', $submission->getAssignment()->getId())->getResult(); foreach ($previousSubmissions as $previousSubmission) { $previousSubmission->setStatus(\Submission::STATUS_NORMAL); Repositories::getEntityManager()->persist($previousSubmission); } $submission->setStatus(\Submission::STATUS_LATEST); $submission->setInfo($response->getDetails()); $submission->setSuccess($response->getFulfillment()); $submission->setOutputfile($outputFile); Repositories::getEntityManager()->persist($submission); Repositories::flushAll(); } return !$error; } catch (Exception $exception) { $errorInformation = "Internal error. Plugin launcher or plugin failed with an internal error. Exception information: " . $exception->getMessage() . " in " . $exception->getFile() . " at " . $exception->getLine(); if ($isTest) { $pluginTest = Repositories::findEntity(Repositories::PluginTest, $rowId); $pluginTest->setStatus(\PluginTest::STATUS_COMPLETED); $pluginTest->setSuccess(0); $pluginTest->setInfo($errorInformation); Repositories::persistAndFlush($pluginTest); } else { $submission = Repositories::findEntity(Repositories::Submission, $rowId); $submission->setStatus(\Submission::STATUS_NORMAL); $submission->setInfo($errorInformation); Repositories::persistAndFlush($submission); } return false; } }
protected function body() { // Validate input. $inputs = array('group' => 'isIndex', 'problem' => 'isIndex', 'deadline' => 'isDate', 'reward' => 'isNonNegativeInt'); if (!$this->isInputValid($inputs)) { return false; } // Load input $id = $this->getParams('id'); $group = $this->getParams('group'); $problem = $this->getParams('problem'); $deadline = $this->getParams('deadline'); $reward = $this->getParams('reward'); // Adjust input $deadline = $deadline . ' 23:59:59'; // Load from database /** * @var $groupEntity \Group * @var $assignmentEntity \Assignment * @var $problemEntity \Problem */ $groupEntity = Repositories::getEntityManager()->find('Group', $group); $problemEntity = Repositories::getEntityManager()->find('Problem', $problem); if ($groupEntity === null || $problemEntity === null) { return $this->stop('Group or problem does not exist.', 'Assignment cannot be edited.'); } // Authenticate $user = User::instance(); if (!$user->hasPrivileges(User::groupsManageAll) && (!$user->hasPrivileges(User::groupsManageOwn) || $groupEntity->getOwner()->getId() !== $user->getId())) { return $this->stop(Language::get(StringID::InsufficientPrivileges)); } // Already exists? if ($id !== null && $id !== '') { $assignmentEntity = Repositories::getEntityManager()->find('Assignment', $id); $assignmentEntity->setDeadline(\DateTime::createFromFormat("Y-m-d H:i:s", $deadline)); $assignmentEntity->setReward($reward); Repositories::getEntityManager()->persist($assignmentEntity); Repositories::getEntityManager()->flush($assignmentEntity); } else { // Verify integrity if ($problemEntity->getLecture()->getId() !== $groupEntity->getLecture()->getId()) { return $this->stop('You are adding an assignment for problem belonging to lecture X to a group that belongs to lecture Y. This is not possible.'); } // Create new $assignmentEntity = new \Assignment(); $assignmentEntity->setGroup($groupEntity); $assignmentEntity->setProblem($problemEntity); $assignmentEntity->setDeadline(\DateTime::createFromFormat("Y-m-d H:i:s", $deadline)); $assignmentEntity->setReward($reward); Repositories::getEntityManager()->persist($assignmentEntity); Repositories::getEntityManager()->flush($assignmentEntity); // Send e-mail /** * @var $subscription \Subscription */ $query = Repositories::getEntityManager()->createQuery('SELECT s, u FROM Subscription s JOIN s.user u WHERE s.group = :group'); $query->setParameter('group', $groupEntity); $subscriptions = $query->getResult(); foreach ($subscriptions as $subscription) { if (!$subscription->getUser()->getSendEmailOnNewAssignment()) { continue; } $to = $subscription->getUser()->getEmail(); $email = file_get_contents(Config::get("paths", "newAssignmentEmail")); $email = str_replace("%{Problem}", $problemEntity->getName(), $email); $email = str_replace("%{Deadline}", $deadline, $email); $email = str_replace("%{Group}", $groupEntity->getName(), $email); $email = str_replace("%{Link}", Config::getHttpRoot() . "#studentAssignments#" . $assignmentEntity->getId(), $email); $email = str_replace("%{Date}", date("Y-m-d H:i:s"), $email); $lines = explode("\n", $email); $subject = $lines[0]; // The first line is subject. $text = preg_replace('/^.*\\n/', '', $email); // Everything except the first line. if (!Core::sendEmail($to, trim($subject), $text)) { Core::logError(Error::create(Error::levelWarning, "E-mail could not be sent to {$to}.")); } } } return true; }
/** * Performs the function of this script. */ protected function body() { if (!$this->userHasPrivileges(User::assignmentsSubmit)) { return; } if (!$this->isInputValid(array('assignmentId' => 'isIndex'))) { return; } $userId = User::instance()->getId(); $assignmentId = $this->getParams('assignmentId'); /** * @var $assignment \Assignment */ $assignment = Repositories::getEntityManager()->find('Assignment', $assignmentId); $query = "SELECT s, a FROM Subscription s, Assignment a WHERE s.group = a.group AND s.user = "******" AND a.id = " . $assignmentId; /** * @var $result \Subscription[] */ $result = Repositories::getEntityManager()->createQuery($query)->getResult(); if (count($result) === 0) { $this->stop(Language::get(StringID::HackerError)); return; } if ($result[0]->getStatus() == \Subscription::STATUS_REQUESTED) { $this->stop(Language::get(StringID::SubscriptionNotYetAccepted)); return; } $submissionsFolder = Config::get('paths', 'submissions'); $file = date('Y-m-d_H-i-s_') . $userId . '_' . StringUtils::randomString(10) . '.zip'; if (!$this->saveUploadedFile('submission', $submissionsFolder . $file)) { return; } // Create submission $newSubmission = new \Submission(); $newSubmission->setAssignment($assignment); $newSubmission->setSubmissionFile($file); $newSubmission->setUser(User::instance()->getEntity()); $newSubmission->setDate(new \DateTime()); // Put into database Repositories::persistAndFlush($newSubmission); // Launch plugin, or set full success if not connected to any plugin if ($assignment->getProblem()->getPlugin() === null) { $newSubmission->setSuccess(100); $newSubmission->setInfo(Language::get(StringID::NoPluginUsed)); $previousSubmissions = Repositories::makeDqlQuery("SELECT s FROM \\Submission s WHERE s.user = :sameUser AND s.assignment = :sameAssignment AND s.status != 'graded' AND s.status != 'deleted'")->setParameter('sameUser', User::instance()->getEntity()->getId())->setParameter('sameAssignment', $assignment->getId())->getResult(); foreach ($previousSubmissions as $previousSubmission) { $previousSubmission->setStatus(\Submission::STATUS_NORMAL); Repositories::getEntityManager()->persist($previousSubmission); } $newSubmission->setStatus(\Submission::STATUS_LATEST); Repositories::getEntityManager()->persist($newSubmission); Repositories::flushAll(); } else { Core::launchPlugin($assignment->getProblem()->getPlugin()->getType(), Config::get('paths', 'plugins') . $assignment->getProblem()->getPlugin()->getMainfile(), $submissionsFolder . $file, false, $newSubmission->getId(), explode(';', $assignment->getProblem()->getConfig())); } // Run checking for plagiarism $similarityJar = Config::get('paths', 'similarity'); if ($similarityJar != null && is_file($similarityJar)) { $arguments = "comparenew"; // Get config file and autoloader file $paths = Config::get('paths'); $vendorAutoload = $paths['composerAutoload']; $java = Config::get('bin', 'java'); $javaArguments = Config::get('bin', 'javaArguments'); $pathToCore = Config::get('paths', 'core'); // This code will be passed, shell-escaped to the PHP CLI $launchCode = <<<LAUNCH_CODE require_once '{$vendorAutoload}'; chdir("{$pathToCore}"); `"{$java}" {$javaArguments} -Dfile.encoding=UTF-8 -jar "{$similarityJar}" {$arguments}`; LAUNCH_CODE; ShellUtils::phpExecInBackground(Config::get('bin', 'phpCli'), $launchCode); } }
/** * Creates instance and initializes it from $_SESSION if possible. * * Also initializes privilege helper with privilege names (same as constant names). */ protected function __construct() { if (!isset($_SESSION[self::sessionSpace])) { $_SESSION[self::sessionSpace] = null; } $this->data =& $_SESSION[self::sessionSpace]; $privilegeNames = array('usersAdd', 'usersManage', 'usersRemove', 'usersExplore', 'usersPrivPresets', 'groupsJoinPublic', 'groupsJoinPrivate', 'groupsRequest', 'pluginsAdd', 'pluginsManage', 'pluginsRemove', 'pluginsExplore', 'pluginsTest', 'assignmentsSubmit', 'submissionsCorrect', 'lecturesAdd', 'lecturesManageOwn', 'lecturesManageAll', 'groupsAdd', 'groupsManageOwn', 'groupsManageAll', 'otherAdministration', 'submissionsViewAuthors', 'submissionsModifyRated'); $privileges = array(); foreach ($privilegeNames as $name) { $privileges[$name] = constant('self::' . $name); } asort($privileges); $this->privileges = new Flags(array_keys($privileges)); if ($this->isLogged()) { $this->entity = Repositories::getEntityManager()->find('User', $this->data['id']); } }