file = $file; } public function parse(): ParsedFragment { $sectionOpen = null; $extraOpen = false; $extends = null; $js = []; $css = []; $sections = []; $extra = ['', '']; $fileHandle = fopen($this->file, 'r'); if (!$fileHandle) { throw new \Exception('Cannot open file ' . $this->file); } $lineNumber = 0; while (($line = fgets($fileHandle)) !== false) { ++$lineNumber; if (($cssMatched = $this->matchCss($line)) !== null) { $css[] = $cssMatched; continue; } if (($jsMatched = $this->matchJs($line)) !== null) { $js[] = $jsMatched; continue; } if (($extendsMatched = $this->matchExtends($line)) !== null) { if ($extends !== null) { throw new \Exception('Error in file ' . $this->file . ' in line ' . $lineNumber . ' - There is already an \'@extends\' declared.'); } $extends = $extendsMatched; continue; } if (($sectionMatched = $this->matchSection($line)) !== null) { if ($extends === null) { throw new \Exception('Error in file ' . $this->file . ' in line ' . $lineNumber . ' - \'@section\' has no meaning if view extends nothing.'); } if ($sectionOpen !== null) { throw new \Exception('Parse error in file ' . $this->file . ' in line ' . $lineNumber . ' - A \'@section\' is already open (no \'@endsection\' found).'); } $sectionOpen = $sectionMatched; $sections[$sectionOpen] = ''; continue; } if ($this->matchEndSection($line)) { if ($sectionOpen === null) { throw new \Exception('Parse error in file ' . $this->file . ' in line ' . $lineNumber . ' - Cannot end section until no \'@section\' is open.'); } $sectionOpen = null; } if ($this->matchExtra($line)) { if ($extraOpen) { throw new \Exception('Parse error in file ' . $this->file . ' in line ' . $lineNumber . ' - An \'@extra\' is already open (no \'@endextra\' found).'); } $extraOpen = true; continue; } if ($this->matchEndExtra($line)) { if (!$extraOpen) { throw new \Exception('Parse error in file ' . $this->file . ' in line ' . $lineNumber . ' - Cannot end extra until no \'@extra\' is open.'); } $extraOpen = false; } if ($sectionOpen !== null) { $sections[$sectionOpen] .= $line; } if ($extraOpen) { $offset = $extends === null ? 0 : 1; $extra[$offset] .= $line; } } fclose($fileHandle); return new ParsedFragment($extends, $css, $js, $sections, $extra); } private function matchCss(string $line): ?string { if (preg_match('/^\s*@css\((.*)\)\s*$/', $line, $matches) === 1) { return $matches[1]; } return null; } private function matchJs(string $line): ?string { if (preg_match('/^\s*@js\((.*)\)\s*$/', $line, $matches) === 1) { return $matches[1]; } return null; } private function matchExtends(string $line): ?string { if (preg_match('/^\s*@extends\(([\w\/]+)\)\s*$/', $line, $matches) === 1) { return $matches[1]; } return null; } private function matchSection(string $line): ?string { if (preg_match('/^\s*@section\((\w+)\)\s*$/', $line, $matches) === 1) { return $matches[1]; } return null; } private function matchEndSection(string $line): bool { return preg_match('/^\s*@endsection(?:\(\))?\s*$/', $line) === 1; } private function matchExtra(string $line): bool { return preg_match('/^\s*@extra(?:\(\))?\s*$/', $line) === 1; } private function matchEndExtra(string $line): bool { return preg_match('/^\s*@endextra(?:\(\))?\s*$/', $line) === 1; } }