pgnFile = $this->sanitize($pgnFile); if (!file_exists($this->pgnFile)) { throw new Exception("File not found: " . $this->pgnFile); } } $this->_fullParsing = $fullParsing; $this->gameParser = new GameParser(); $this->pgnGameParser = new PgnGameParser(); } private function sanitize($filePath) { $extension = $this->getExtension($filePath); if ($extension != 'pgn') return null; if (class_exists("LudoDBRegistry")) { $tempPath = LudoDBRegistry::get('FILE_UPLOAD_PATH'); } else { $tempPath = null; } if (isset($tempPath) && substr($filePath, 0, strlen($tempPath)) == $tempPath) { } else { if (substr($filePath, 0, 1) === "/") return null; } $filePath = preg_replace("/[^0-9\.a-z_\-\/]/si", "", $filePath); if (!file_exists($filePath)) return null; return $filePath; } private function getExtension($filePath) { $tokens = explode(".", $filePath); return strtolower(array_pop($tokens)); } public function setPgnContent($content) { $this->pgnContent = $content; } private function cleanPgn() { $c = $this->pgnContent; /* replace CR and TAB with space */ $c = preg_replace("/[\t\r]/s", " ", $c); /* separate first comment of variation */ $c = str_replace("({", "( {", $c); /* replace 0 in castle with O */ $c = str_replace("0-0-0", "O-O-O", $c); $c = str_replace("0-0", "O-O", $c); /* basic trimming: * - remove initial blanks * - keep only one space * - trim lines * - max 2 consecutive '\n' */ $c = preg_replace("/^\s+([^\s])/", "$1", $c); $c = preg_replace("/ +/", " ", $c); $c = preg_replace("/\s*\n\s*/", "\n", $c); $c = preg_replace("/\n{3,}/s", "\n\n", $c); /* replace '[' between '{' and '}' with '//--SB--//' */ $c = preg_replace('/(?:\G(?!\A)|\{)[^\}\[]*\K\[/', "//--SB--//", $c); $c = preg_replace('/(?:\G(?!\A)|\{)[^\}\]]*\K\]/', "//--SE--//", $c); /* set one '\n' between tags. * This is possible because brackets within comments are protected above */ $c = preg_replace('/"\]\s*\[/s', "\"]\n[", $c); /* set '\n\n' between tags and movetext section * set '\n\n' between non tag line and tag line (between two games) * This is possible because brackets within comments are protected above */ $c = preg_replace('/"\]\s*([\.0-9]|{)/s', "\"]\n\n$1", $c); $c = preg_replace("/([^\]])\n+\[/", "$1\n\n[", $c); /* revert brackets within movetext comments */ $c = str_replace("//--SB--//", "[", $c); $c = str_replace("//--SE--//", "]", $c); return $c; } public static function getArrayOfGames($pgn) { return self::getPgnGamesAsArray($pgn); } private function splitPgnIntoGames($pgnString) { return $this->getPgnGamesAsArray($pgnString); } private function getPgnGamesAsArray($pgn) { $ret = array(); $content = "\n\n" . $pgn; $games = preg_split("/\n\n\[/s", $content, -1, PREG_SPLIT_DELIM_CAPTURE); //file_put_contents("/tmp/parsed.pgn", $content); for ($i = 1, $count = count($games); $i < $count; $i++) { $gameContent = trim("[" . $games[$i]); if (strlen($gameContent) > 10) { array_push($ret, $gameContent); } } return $ret; } public function getGamesAsJSON() { return json_encode($this->getGames()); } private function fullParsing() { return $this->_fullParsing; } public function getUnparsedGames() { if (!isset($this->pgnGames)) { if ($this->pgnFile && !isset($this->pgnContent)) { $this->pgnContent = file_get_contents($this->pgnFile); } $this->pgnGames = $this->splitPgnIntoGames($this->cleanPgn($this->pgnContent)); } return $this->pgnGames; } public function countGames() { $games = $this->getUnparsedGames(); return count($games); } public function getCleanPgn() { return $this->cleanPgn($this->pgnContent); } public function getFirstGame() { return $this->getGameByIndex(0); } public function getGameByIndexShort($index) { $games = $this->getUnparsedGames(); if (count($games) && count($games) > $index) { $game = $this->getParsedGame($games[$index]); $game["moves"] = $this->toShortVersion($game["moves"]); return $game; } return null; } public function getGameByIndex($index) { $games = $this->getUnparsedGames(); if (count($games) && count($games) > $index) { return $this->getParsedGame($games[$index]); } return null; } public function getGames() { return $this->getParsedGames(false); } public function getGamesShort() { return $this->getParsedGames(true); } private function getParsedGames($short = false) { $games = $this->getUnparsedGames(); $ret = array(); for ($i = 0, $count = count($games); $i < $count; $i++) { try { $g = $short ? $this->getParsedGameShort($games[$i]) : $this->getParsedGame($games[$i]); $ret[] = $g; } catch (Exception $e) { } } return $ret; } private function toShortVersion($branch) { foreach ($branch as &$move) { if (isset($move["from"])) { $move["n"] = $move["from"] . $move["to"]; unset($move["fen"]); unset($move["from"]); unset($move["to"]); if (isset($move["variations"])) { $move["v"] = array(); foreach ($move["variations"] as $variation) { $move["v"][] = $this->toShortVersion($variation); } } unset($move["variations"]); } } return $branch; } private function getParsedGame($unParsedGame) { $this->pgnGameParser->setPgn($unParsedGame); $ret = $this->pgnGameParser->getParsedData(); if ($this->fullParsing()) { $ret = $this->gameParser->getParsedGame($ret); } return $ret; } private function getParsedGameShort($unParsedGame) { $this->pgnGameParser->setPgn($unParsedGame); $ret = $this->pgnGameParser->getParsedData(); if ($this->fullParsing()) { $ret = $this->gameParser->getParsedGame($ret, true); $moves = &$ret["moves"]; $moves = $this->toShortVersion($moves); } return $ret; } }