ILIAS  trunk Revision v11.0_alpha-1761-g6dbbfa7b760
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
EntriesYamlParser.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
25 
26 /***
27  * @author Timon Amstutz <timon.amstutz@ilub.unibe.ch>
28  * @version $Id$
29  */
30 class EntriesYamlParser implements YamlParser
31 {
32  public const PARSER_STATE_OUTSIDE = 1;
33  public const PARSER_STATE_ENTRY = 2;
34  public const PARSER_STATE_SEEKING_RETURN = 3;
36 
37  protected array $items = array();
38  protected ?Exception\Factory $ef = null;
39 
43  protected string $file_path = "none";
44 
48  public function __construct()
49  {
50  $this->ef = new Exception\Factory();
51  }
52 
56  public function parseYamlStringArrayFromFile(string $filePath): array
57  {
58  $this->file_path = $filePath;
59  $content = $this->getFileContentAsString($filePath);
60  return $this->parseYamlStringArrayFromString($content);
61  }
62 
66  public function parseArrayFromFile(string $filePath): array
67  {
68  $this->file_path = $filePath;
69  $content = $this->getFileContentAsString($filePath);
70  return $this->parseArrayFromString($content);
71  }
72 
76  public function parseEntriesFromFile(string $filePath): Entry\ComponentEntries
77  {
78  $this->file_path = $filePath;
79  $content = $this->getFileContentAsString($filePath);
80  return $this->parseEntriesFromString($content);
81  }
82 
86  public function parseYamlStringArrayFromString(string $content): array
87  {
88  return $this->getYamlEntriesFromString($content);
89  }
90 
94  public function parseArrayFromString(string $content): array
95  {
96  return $this->getPHPArrayFromYamlArray(
97  $this->getYamlEntriesFromString($content)
98  );
99  }
100 
101  public function parseEntriesFromString(string $content): Entry\ComponentEntries
102  {
103  $entries_array = $this->parseArrayFromString($content);
104  return $this->getEntriesFromArray($entries_array);
105  }
106 
110  protected function getFileContentAsString(string $filePath): string
111  {
112  if (!file_exists($filePath)) {
113  throw $this->ef->exception(Exception\CrawlerException::INVALID_FILE_PATH, $filePath);
114  }
115  $content = file_get_contents($filePath);
116  if (!$content) {
117  throw $this->ef->exception(Exception\CrawlerException::FILE_OPENING_FAILED, $filePath);
118  }
119  return $content;
120  }
121 
125  protected function getYamlEntriesFromString(string $content): array
126  {
127  $parser_state = self::PARSER_STATE_OUTSIDE;
128  $current_entry = "";
129  $yaml_entries = array();
130 
131  foreach (preg_split("/((\r?\n)|(\r\n?))/", $content) as $line) {
132  if ($parser_state === self::PARSER_STATE_OUTSIDE) {
133  if (preg_match('/---/', $line)) {
134  $current_entry = "";
135  $parser_state = self::PARSER_STATE_ENTRY;
136  }
137  if (preg_match('/\@return/', $line)) {
138  throw $this->ef->exception(
139  Exception\CrawlerException::ENTRY_WITH_NO_YAML_DESCRIPTION,
140  " in file: " . $this->file_path . ", " . $line
141  );
142  }
143  if (preg_match('/public function (.*)\(/', $line)) {
144  throw $this->ef->exception(
145  Exception\CrawlerException::ENTRY_WITH_NO_YAML_DESCRIPTION,
146  " in file: " . $this->file_path . ", " . $line
147  );
148  }
149  } elseif ($parser_state === self::PARSER_STATE_ENTRY) {
150  if (!preg_match('/(\*$)|(---)/', $line)) {
151  $current_entry .= $this->purifyYamlLine($line);
152  }
153  if (preg_match('/---/', $line)) {
154  $parser_state = self::PARSER_STATE_SEEKING_RETURN;
155  }
156  if (preg_match('/\@return/', $line)) {
157  throw $this->ef->exception(
158  Exception\CrawlerException::ENTRY_WITH_NO_YAML_DESCRIPTION,
159  " in file: " . $this->file_path . ", " . $line
160  );
161  }
162  if (preg_match('/public function (.*)\(/', $line)) {
163  throw $this->ef->exception(
164  Exception\CrawlerException::ENTRY_WITH_NO_YAML_DESCRIPTION,
165  " in file: " . $this->file_path . ", " . $line
166  );
167  }
168  } elseif ($parser_state === self::PARSER_STATE_SEEKING_RETURN) {
169  if (preg_match('/\@return/', $line)) {
170  $current_entry .= "namespace: " . ltrim($this->purifyYamlLine($line), '@return');
171  $parser_state = self::PARSER_STATE_SEEKING_FUNCTION_NAME;
172  }
173  if (preg_match('/---/', $line)) {
174  throw $this->ef->exception(
175  Exception\CrawlerException::ENTRY_WITH_NO_VALID_RETURN_STATEMENT,
176  " in file: " . $this->file_path . " line " . $current_entry
177  );
178  }
179  if (preg_match('/public function (.*)\(/', $line)) {
180  throw $this->ef->exception(
181  Exception\CrawlerException::ENTRY_WITH_NO_VALID_RETURN_STATEMENT,
182  " in file: " . $this->file_path . " line " . $current_entry
183  );
184  }
185  } else {
186  if (preg_match('/public function (.*)\(/', $line, $matches)) {
187  preg_match('/public function (.*)\(/', $line, $matches);
188  $current_entry .= "function_name: " . $matches[1];
189  $yaml_entries[] = $current_entry;
190  $parser_state = self::PARSER_STATE_OUTSIDE;
191  }
192  if (preg_match('/---/', $line)) {
193  throw $this->ef->exception(
194  Exception\CrawlerException::ENTRY_WITHOUT_FUNCTION,
195  " in file: " . $this->file_path . " line " . $current_entry
196  );
197  }
198  }
199  }
200  if ($parser_state === self::PARSER_STATE_SEEKING_RETURN) {
201  throw $this->ef->exception(
202  Exception\CrawlerException::ENTRY_WITH_NO_VALID_RETURN_STATEMENT,
203  " in file: " . $this->file_path . " line " . $current_entry
204  );
205  } elseif ($parser_state === self::PARSER_STATE_ENTRY) {
206  throw $this->ef->exception(
207  Exception\CrawlerException::ENTRY_WITH_NO_YAML_DESCRIPTION,
208  " in file: " . $this->file_path
209  );
210  } elseif ($parser_state === self::PARSER_STATE_SEEKING_FUNCTION_NAME) {
211  throw $this->ef->exception(
212  Exception\CrawlerException::ENTRY_WITHOUT_FUNCTION,
213  " in file: " . $this->file_path
214  );
215  }
216  return $yaml_entries;
217  }
218 
219  protected function purifyYamlLine(string $line): string
220  {
221  return str_replace("* ", "", ltrim($line)) . PHP_EOL;
222  }
223 
227  protected function getPHPArrayFromYamlArray(array $yaml_entries): array
228  {
229  $entries = array();
230  $parser = new Yaml\Parser();
231 
232  foreach ($yaml_entries as $yaml_entry) {
233  try {
234  $entries[] = $parser->parse($yaml_entry);
235  } catch (\Exception $e) {
236  throw $this->ef->exception(Exception\CrawlerException::PARSING_YAML_ENTRY_FAILED, " file: " . $this->file_path . "; " . $e);
237  }
238  }
239 
240 
241  array_walk_recursive($entries, function (&$item) {
242  if (!is_null($item)) {
243  $item = rtrim($item, PHP_EOL);
244  } else {
245  $item = '';
246  }
247  });
248 
249  return $entries;
250  }
251 
252  protected function getEntriesFromArray(array $entries_array): Entry\ComponentEntries
253  {
254  $entries = new Entry\ComponentEntries();
255 
256  foreach ($entries_array as $entry_data) {
257  $entries->addEntry($this->getEntryFromData($entry_data));
258  }
259 
260  return $entries;
261  }
262 
266  protected function getEntryFromData(array $entry_data): Entry\ComponentEntry
267  {
268  $entry_data['title'] = self::fromCamelCaseToWords($entry_data['function_name']);
269 
270  if (!array_key_exists("title", $entry_data) || !$entry_data['title'] || $entry_data['title'] == "") {
271  throw $this->ef->exception(Exception\CrawlerException::ENTRY_TITLE_MISSING, " File: " . $this->file_path);
272  }
273  if (!array_key_exists("namespace", $entry_data) || !$entry_data['namespace'] || $entry_data['namespace'] == "") {
274  throw $this->ef->exception(Exception\CrawlerException::ENTRY_WITH_NO_VALID_RETURN_STATEMENT, " File: " . $this->file_path);
275  }
276  $entry_data['namespace'] = str_replace('[]', '', $entry_data['namespace']);
277 
278  $entry_data['id'] = str_replace(
279  "\\",
280  "",
281  str_replace("\\ILIAS\\UI\\", "", str_replace("\\ILIAS\\UI\\Component\\", "", $entry_data['namespace']))
282  )
283  . self::toUpperCamelCase($entry_data['title'], ' ');
284  $entry_data['abstract'] = preg_match("/Factory/", $entry_data['namespace']);
285  $entry_data['path'] = str_replace("/ILIAS/UI", "components/ILIAS/UI/src", str_replace("\\", "/", $entry_data['namespace']));
286 
287  if (str_contains($entry_data['path'], 'tests/UI/')) {
288  $entry_data['path'] = str_replace("tests/UI/", "components/ILIAS/UI/tests/", $entry_data['path']);
289  }
290 
291  try {
292  $entry = new Entry\ComponentEntry($entry_data);
293  } catch (\Exception $e) {
294  throw $this->ef->exception(
295  Exception\CrawlerException::PARSING_YAML_ENTRY_FAILED,
296  " could not convert data to entry, message: '" . $e->getMessage() . "' file: " . $this->file_path
297  );
298  }
299 
300  return $entry;
301  }
302 
306  public static function toUpperCamelCase(string $string, string $seperator)
307  {
308  return str_replace($seperator, '', ucwords($string));
309  }
310 
314  public static function toLowerCamelCase(string $string, string $seperator)
315  {
316  return str_replace($seperator, '', lcfirst(ucwords($string)));
317  }
318 
319  public static function fromCamelCaseToWords(string $camelCaseString): string
320  {
321  return implode(' ', preg_split('/(?<=[a-z])(?=[A-Z])/x', ucwords($camelCaseString)));
322  }
323 }
static toLowerCamelCase(string $string, string $seperator)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static toUpperCamelCase(string $string, string $seperator)
parseEntriesFromString(string $content)
Returns a list UI Component Entries of the parsed YAML entries in a given string. ...
string $file_path
Used to add for Information in Exceptions.
Parses information from UI components.
Definition: YamlParser.php:28
static fromCamelCaseToWords(string $camelCaseString)