diff --git a/Facades/DocsFacade/MarkdownPrinters/ActionMarkdownPrinter.php b/Facades/DocsFacade/MarkdownPrinters/ActionMarkdownPrinter.php new file mode 100644 index 000000000..d8d6814f2 --- /dev/null +++ b/Facades/DocsFacade/MarkdownPrinters/ActionMarkdownPrinter.php @@ -0,0 +1,82 @@ +workbench = $workbench; + $this->action = $action; + $this->headingLevel = $headingLevel; + } + + /** + * Builds and returns the complete Markdown for the current action + */ + public function getMarkdown(): string + { + $heading = MarkdownDataType::buildMarkdownHeader($this->action->getName(), $this->headingLevel); + + $uxon = $this->action->exportUxonObject(); + + $uxon = $uxon->toJson(); + //Uxon + + //TODO Einbauen Uxon im Codeblock, mögliche Description + + return <<workbench = $workbench; + $this->group = $group; + $this->headingLevel = $headingLevel; + } + + /** + * Builds and returns the complete Markdown for the current group + */ + public function getMarkdown(): string + { + $heading = MarkdownDataType::buildMarkdownHeader($this->group->getAlias(), $this->headingLevel); + + $rows = []; + + try { + $attributes = $this->group->getAttributes(); + + foreach ($attributes as $attribute) { + if (!$attribute instanceof MetaAttributeInterface) { + continue; + } + + $name = (string) $attribute->getName(); + $alias = (string) $attribute->getAlias(); + + // Minimaler Hinweis, ohne Relation auszubauen/aufzulösen + $note = ''; + if (method_exists($attribute, 'isRelation') && $attribute->isRelation()) { + $note = ' (Relation)'; + } + + // Pipes escapen, damit die Tabelle nicht kaputt geht + $name = str_replace('|', '\|', $name); + $alias = str_replace('|', '\|', $alias); + + $rows[] = "| {$name} | {$alias}{$note} |"; + } + } catch (\Throwable $e) { + // bewusst still; alternativ: Fehlerzeile in die Tabelle + } + + $table = "| Name | Alias |\n|---|---|\n"; + $table .= $rows ? implode("\n", $rows) . "\n" : "| _keine_ | _keine_ |\n"; + + return <<workbench = $workbench; + + if ($filePath) { + + $normalizedPath = $this->normalizePath(rawurldecode($filePath)); + + [$appAlias, $relativePath] = $this->extractAppAndRelativePath($normalizedPath); + + if ($appAlias !== '') { + $this->app = $this->workbench->getApp($appAlias); + } + + if ($relativePath !== '') { + $this->docsPath = $relativePath; + } + } + } + + /** + * Reads the markdown document and returns its content. + * * + * @return string Markdown content + */ + public function getMarkdown(): string + { + $path = $this->getAbsolutePath(); + if(!$path){ + return 'ERROR: file not found!'; + } + if(!StringDataType::endsWith($path, '.php')) { + return "ERROR: This path does not refer to a PHP file. Therefore, the file could not be read."; + } + + return $this->rebasePaths($this->readFile($path)); + } + + /** + * Normalizes a file path to use a consistent directory separator. + * + * All slash variants are converted to the system directory separator + * and duplicate separators are collapsed. + * + * @param string $path Raw path + * @return string Normalized path + */ + protected function normalizePath(string $path): string + { + $path = str_replace(['\/', '\\'], '/', $path); + $path = preg_replace('#/+#', '/', $path); + $path = str_replace('/', DIRECTORY_SEPARATOR, $path); + + $pattern = '#'.preg_quote(DIRECTORY_SEPARATOR).'+' . '#'; + $path = preg_replace($pattern, DIRECTORY_SEPARATOR, $path); + + return $path; + } + + /** + * Extracts app alias and relative path from an api docs path. + * + * Expected pattern: + * api/docs/Vendor/App/some/path/file.php + * becomes: + * alias: "vendor.app" + * relativePath: "some/path/file.php" + * + * @param string $link Normalized path + * @return array{0:string,1:string} [appAlias, relativePath] + */ + protected function extractAppAndRelativePath(string $link): array + { + $link = $this->normalizePath($link); + + $ds = preg_quote(DIRECTORY_SEPARATOR, '#'); + $pattern = "#api{$ds}docs{$ds}([^{$ds}]+){$ds}([^{$ds}]+){$ds}(.+)$#i"; + + if (preg_match($pattern, $link, $m)) { + $appAlias = strtolower($m[1] . "." . $m[2]); + $relativePath = $m[3]; + return [$appAlias, $relativePath]; + } + + return ['', '']; + } + + /** + * Returns the absolute file system path to the current markdown file. + * + * @return string Absolute path to the markdown file + */ + public function getAbsolutePath(): ?string + { + if (! $this->app || ! $this->docsPath) { + return null; + } + + return $this->app->getDirectoryAbsolutePath() + . DIRECTORY_SEPARATOR + . $this->docsPath; + } + + + + /** + * Reads the content of a markdown file from disk. + * + * If the file does not exist an error message is returned instead. + * + * @param string $filePath Absolute path to the markdown file + * @return string File content or error message + */ + protected function readFile(string $filePath): string + { + if (! file_exists($filePath)) { + return 'ERROR: file not found!'; + } + + $md = file_get_contents($filePath); + return $md === false ? '' : $md; + } + + /** + * Rewrites specific PHP use statements by inserting the api docs prefix. + * + * The raw input contains PHP code as a string. All matching use statements + * beginning with "use exface\" are rewritten so they begin with + * "use api\docs\exface\" instead. Other lines remain unchanged. + */ + protected function rebasePaths(string $raw) : string + { + return preg_replace( + '/^use\s+exface\\\\(.*);/m', + 'use api\\docs\\exface\\\\$1;', + $raw + ); + } + + + + + +} \ No newline at end of file diff --git a/Facades/DocsFacade/MarkdownPrinters/ObjectMarkdownPrinter.php b/Facades/DocsFacade/MarkdownPrinters/ObjectMarkdownPrinter.php index 706b2b330..4744027c4 100644 --- a/Facades/DocsFacade/MarkdownPrinters/ObjectMarkdownPrinter.php +++ b/Facades/DocsFacade/MarkdownPrinters/ObjectMarkdownPrinter.php @@ -11,12 +11,14 @@ use exface\Core\Facades\DocsFacade; use exface\Core\Factories\MetaObjectFactory; use exface\Core\Factories\QueryBuilderFactory; +use exface\Core\Interfaces\Actions\ActionInterface; use exface\Core\Interfaces\Model\BehaviorInterface; use exface\Core\Interfaces\Model\MetaAttributeInterface; use exface\Core\Interfaces\Model\MetaAttributeListInterface; use exface\Core\Interfaces\Model\MetaObjectInterface; use exface\Core\Interfaces\Model\MetaRelationInterface; use exface\Core\Interfaces\WorkbenchInterface; +use Respect\Validation\Rules\Length; /** * Builds a Markdown documentation view for a meta object and its related objects. @@ -87,7 +89,11 @@ public function getMarkdown(): string $importantAttributes = trim($importantAttributes); $attributesHeading = MarkdownDataType::buildMarkdownHeader("Attributes of \"{$metaObject->getName()}\"", $headingLevel + 1); - + + $actionHeading = MarkdownDataType::buildMarkdownHeader("Actions of \"{$metaObject->getName()}\"", $headingLevel + 1); + + $groupHeading = MarkdownDataType::buildMarkdownHeader("Attributegroups of \"{$metaObject->getName()}\"", $headingLevel + 1); + $markdown = <<buildMdAttributesSections($metaObject, $headingLevel+2)} +{$this->buildMdActionSection($actionHeading, $metaObject, $headingLevel+2 )} + +{$this->buildMdAttributeGroupSection($groupHeading, $metaObject, $headingLevel+2 )} + {$this->buildMdBehaviorsSections($metaObject, 'Behaviors of "' . $metaObject->getName() . '"', $headingLevel+1)} {$this->buildMdRelatedObjects($metaObject->getRelations(), 'Related objects', $headingLevel)} @@ -172,6 +182,45 @@ protected function buildMarkDownAttributeSection(MetaAttributeInterface $attr, i {$this->buildMdUxonCodeblock($attr->getCustomDataTypeUxon(), 'Configuration of data type [' . $dataType->getAliasWithNamespace() . '](' . $dataTypeLink . '):')} +MD; + + } + + protected function buildMdActionSection(string $header, MetaObjectInterface $obj, int $headingLevel = 3) : string + { + + $markdown = ''; + try{ + foreach ($obj->getActions() as $act) { + $actionPrinter = new ActionMarkdownPrinter($this->workbench, $act, $headingLevel); + $markdown .= $actionPrinter->getMarkdown(); + } + }catch (\Exception $e){ + + } + + return <<getAttributeGroups(); + foreach ($groups as $group) { + $groupPrinter = new AttributeGroupMarkdownPrinter($this->workbench, $group, $headingLevel); + $markdown .= $groupPrinter->getMarkdown(); + } + + return <<getUri()->getPath(), diff --git a/Interfaces/Facades/MarkdownPrinterMiddlewareInterface.php b/Interfaces/Facades/MarkdownPrinterMiddlewareInterface.php index 029e47d9b..651dab9c9 100644 --- a/Interfaces/Facades/MarkdownPrinterMiddlewareInterface.php +++ b/Interfaces/Facades/MarkdownPrinterMiddlewareInterface.php @@ -8,4 +8,7 @@ interface MarkdownPrinterMiddlewareInterface extends MiddlewareInterface { public function getMarkdown(ServerRequestInterface $request) : string; + + + public function shouldSkip(ServerRequestInterface $request) : bool; } \ No newline at end of file