コード例 #1
0
 /**
  * @param ExerciseInterface $exercise
  * @param string $fileName
  * @return ResultInterface
  */
 public function check(ExerciseInterface $exercise, $fileName)
 {
     if (!$exercise instanceof FunctionRequirementsExerciseCheck) {
         throw new \InvalidArgumentException();
     }
     $requiredFunctions = $exercise->getRequiredFunctions();
     $bannedFunctions = $exercise->getBannedFunctions();
     $code = file_get_contents($fileName);
     try {
         $ast = $this->parser->parse($code);
     } catch (Error $e) {
         return Failure::fromCheckAndCodeParseFailure($this, $e, $fileName);
     }
     $visitor = new FunctionVisitor($requiredFunctions, $bannedFunctions);
     $traverser = new NodeTraverser();
     $traverser->addVisitor($visitor);
     $traverser->traverse($ast);
     $bannedFunctions = [];
     if ($visitor->hasUsedBannedFunctions()) {
         $bannedFunctions = array_map(function (FuncCall $node) {
             return ['function' => $node->name->__toString(), 'line' => $node->getLine()];
         }, $visitor->getBannedUsages());
     }
     $missingFunctions = [];
     if (!$visitor->hasMetFunctionRequirements()) {
         $missingFunctions = $visitor->getMissingRequirements();
     }
     if (!empty($bannedFunctions) || !empty($missingFunctions)) {
         return new FunctionRequirementsFailure($this, $bannedFunctions, $missingFunctions);
     }
     return Success::fromCheck($this);
 }
コード例 #2
0
 /**
  * @param ExerciseInterface $exercise
  * @return ExerciseInterface
  */
 private function validateExercise(ExerciseInterface $exercise)
 {
     $type = $exercise->getType();
     $requiredInterface = $type->getExerciseInterface();
     if (!$exercise instanceof $requiredInterface) {
         throw InvalidArgumentException::missingImplements($exercise, $requiredInterface);
     }
     return $exercise;
 }
コード例 #3
0
ファイル: RunnerFactory.php プロジェクト: jacmoe/php-workshop
 /**
  * @param ExerciseInterface $exercise
  * @param EventDispatcher $eventDispatcher
  * @return ExerciseRunnerInterface
  */
 public function create(ExerciseInterface $exercise, EventDispatcher $eventDispatcher)
 {
     switch ($exercise->getType()->getValue()) {
         case ExerciseType::CLI:
             return new CliRunner($exercise, $eventDispatcher);
         case ExerciseType::CGI:
             return new CgiRunner($exercise, $eventDispatcher);
     }
     throw new InvalidArgumentException(sprintf('Exercise Type: "%s" not supported', $exercise->getType()->getValue()));
 }
コード例 #4
0
ファイル: CodePatcher.php プロジェクト: jacmoe/php-workshop
 /**
  * @param ExerciseInterface $exercise
  * @param string $code
  * @return string
  */
 public function patch(ExerciseInterface $exercise, $code)
 {
     if (null !== $this->defaultPatch) {
         $code = $this->applyPatch($this->defaultPatch, $code);
     }
     if ($exercise instanceof SubmissionPatchable) {
         $code = $this->applyPatch($exercise->getPatch(), $code);
     }
     return $code;
 }
コード例 #5
0
 public function testAlteringDatabaseInSolutionDoesNotEffectDatabaseInUserSolution()
 {
     $solution = SingleFileSolution::fromFile(realpath(__DIR__ . '/../res/database/solution-alter-db.php'));
     $this->exercise->expects($this->once())->method('getSolution')->will($this->returnValue($solution));
     $this->exercise->expects($this->any())->method('getArgs')->will($this->returnValue([]));
     $this->exercise->expects($this->atLeastOnce())->method('getType')->will($this->returnValue(ExerciseType::CLI()));
     $this->exercise->expects($this->once())->method('configure')->will($this->returnCallback(function (ExerciseDispatcher $dispatcher) {
         $dispatcher->requireCheck(DatabaseCheck::class);
     }));
     $this->exercise->expects($this->once())->method('seed')->with($this->isInstanceOf(PDO::class))->will($this->returnCallback(function (PDO $db) {
         $db->exec('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER, gender TEXT)');
         $stmt = $db->prepare('INSERT into users (name, age, gender) VALUES (:name, :age, :gender)');
         $stmt->execute([':name' => 'Jimi Hendrix', ':age' => 27, ':gender' => 'Male']);
     }));
     $this->exercise->expects($this->once())->method('verify')->with($this->isInstanceOf(PDO::class))->will($this->returnCallback(function (PDO $db) {
         $users = $db->query('SELECT * FROM users');
         $users = $users->fetchAll(PDO::FETCH_ASSOC);
         $this->assertEquals([['id' => 1, 'name' => 'Jimi Hendrix', 'age' => '27', 'gender' => 'Male'], ['id' => 2, 'name' => 'Kurt Cobain', 'age' => '27', 'gender' => 'Male']], $users);
     }));
     $results = new ResultAggregator();
     $eventDispatcher = new EventDispatcher($results);
     $checkRepository = new CheckRepository([$this->check]);
     $dispatcher = new ExerciseDispatcher(new RunnerFactory(), $results, $eventDispatcher, $checkRepository);
     $dispatcher->verify($this->exercise, __DIR__ . '/../res/database/user-solution-alter-db.php');
 }
コード例 #6
0
ファイル: ComposerCheck.php プロジェクト: jacmoe/php-workshop
 /**
  * @param ExerciseInterface $exercise
  * @param string $fileName
  * @return ResultInterface
  */
 public function check(ExerciseInterface $exercise, $fileName)
 {
     if (!$exercise instanceof ComposerExerciseCheck) {
         throw new \InvalidArgumentException();
     }
     if (!file_exists(sprintf('%s/composer.json', dirname($fileName)))) {
         return new Failure($this->getName(), 'No composer.json file found');
     }
     if (!file_exists(sprintf('%s/composer.lock', dirname($fileName)))) {
         return new Failure($this->getName(), 'No composer.lock file found');
     }
     $lockFile = new LockFileParser(sprintf('%s/composer.lock', dirname($fileName)));
     $missingPackages = array_filter($exercise->getRequiredPackages(), function ($package) use($lockFile) {
         return !$lockFile->hasInstalledPackage($package);
     });
     if (count($missingPackages) > 0) {
         return new Failure($this->getName(), sprintf('Lockfile doesn\'t include the following packages at any version: "%s"', implode('", "', $missingPackages)));
     }
     return new Success($this->getName());
 }
コード例 #7
0
 public function testVerify()
 {
     $this->createExercise();
     $this->exercise->expects($this->once())->method('configure')->with($this->exerciseDispatcher);
     $this->check->expects($this->once())->method('check')->will($this->returnValue(new Success('Success')));
     $this->check->expects($this->once())->method('canRun')->with($this->exerciseType)->will($this->returnValue(true));
     $this->check->expects($this->once())->method('getExerciseInterface')->will($this->returnValue(ExerciseInterface::class));
     $this->mockRunner();
     $this->runner->expects($this->once())->method('verify')->with($this->file)->will($this->returnValue($this->getMock(SuccessInterface::class)));
     $this->exerciseDispatcher->requireCheck(get_class($this->check), ExerciseDispatcher::CHECK_BEFORE);
     $result = $this->exerciseDispatcher->verify($this->exercise, $this->file);
     $this->assertInstanceOf(ResultAggregator::class, $result);
     $this->assertTrue($result->isSuccessful());
 }
コード例 #8
0
 /**
  * @param ExerciseInterface $exercise
  * @param $interface
  * @return static
  */
 public static function missingImplements(ExerciseInterface $exercise, $interface)
 {
     return new static(sprintf('Exercise: "%s" should implement interface: "%s"', $exercise->getName(), $interface));
 }
コード例 #9
0
 /**
  * @param EventDispatcher $eventDispatcher
  * @param ExerciseInterface $exercise
  */
 private function dispatchExerciseSelectedEvent(EventDispatcher $eventDispatcher, ExerciseInterface $exercise)
 {
     $eventDispatcher->dispatch(new Event(sprintf('exercise.selected.%s', AbstractExercise::normaliseName($exercise->getName()))));
 }
コード例 #10
0
 /**
  * Whether the factory supports this exercise type.
  *
  * @param ExerciseInterface $exercise
  * @return bool
  */
 public function supports(ExerciseInterface $exercise)
 {
     return $exercise->getType()->getValue() === self::$type;
 }
コード例 #11
0
 /**
  * @param ExerciseInterface $exercise
  * @param UserState $userState
  * @param OutputInterface $output
  */
 private function renderSuccessInformation(ExerciseInterface $exercise, UserState $userState, OutputInterface $output)
 {
     $output->emptyLine();
     $output->writeLine($this->style(" PASS!", ['green', 'bg_default', 'bold']));
     $output->emptyLine();
     $output->writeLine("Here's the official solution in case you want to compare notes:");
     $output->writeLine($this->lineBreak());
     foreach ($exercise->getSolution()->getFiles() as $file) {
         $output->writeLine($this->style($file->getRelativePath(), ['bold', 'cyan', 'underline']));
         $output->emptyLine();
         $code = $file->getContents();
         if (pathinfo($file->getRelativePath(), PATHINFO_EXTENSION) === 'php') {
             $code = $this->syntaxHighlighter->highlight($code);
         }
         //make sure there is a new line at the end
         $code = preg_replace('/\\n$/', '', $code) . "\n";
         $output->write($code);
         $output->writeLine($this->lineBreak());
     }
     $completedCount = count($userState->getCompletedExercises());
     $numExercises = $this->exerciseRepository->count();
     $output->writeLine(sprintf('You have %d challenges left.', $numExercises - $completedCount));
     $output->writeLine(sprintf('Type "%s" to show the menu.', $this->appName));
     $output->emptyLine();
 }
コード例 #12
0
 /**
  * Static constructor to create an instance from the check & exercise.
  *
  * @param CheckInterface $check The check Instance.
  * @param ExerciseInterface $exercise The exercise Instance.
  * @return static
  */
 public static function fromCheckAndExercise(CheckInterface $check, ExerciseInterface $exercise)
 {
     return new static(sprintf('Check: "%s" cannot process exercise: "%s" with type: "%s"', $check->getName(), $exercise->getName(), $exercise->getType()));
 }
コード例 #13
0
 /**
  * @param CheckInterface[] $checks
  * @param ExerciseInterface $exercise
  * @throws CheckNotApplicableException
  * @throws ExerciseNotConfiguredException
  */
 private function validateChecks(array $checks, ExerciseInterface $exercise)
 {
     foreach ($checks as $check) {
         if (!$check->canRun($exercise->getType())) {
             throw CheckNotApplicableException::fromCheckAndExercise($check, $exercise);
         }
         $checkInterface = $check->getExerciseInterface();
         if (!$exercise instanceof $checkInterface) {
             throw ExerciseNotConfiguredException::missingImplements($exercise, $checkInterface);
         }
     }
 }