TYPO3  7.6
DocbookGenerator.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Fluid\Service;
3 
4 /* *
5  * This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
6  * *
7  * It is free software; you can redistribute it and/or modify it under *
8  * the terms of the GNU Lesser General Public License, either version 3 *
9  * of the License, or (at your option) any later version. *
10  * *
11  * The TYPO3 project - inspiring people to share! *
12  * */
13 
15 
21 {
28  public function generateDocbook($namespace)
29  {
30  if (substr($namespace, -1) !== \TYPO3\CMS\Fluid\Fluid::NAMESPACE_SEPARATOR) {
31  $namespace .= \TYPO3\CMS\Fluid\Fluid::NAMESPACE_SEPARATOR;
32  }
33  $classNames = $this->getClassNamesInNamespace($namespace);
34  $xmlRootNode = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>
35 <section version="5.0" xmlns="http://docbook.org/ns/docbook"
36  xml:id="fluid.usermanual.standardviewhelpers"
37  xmlns:xl="http://www.w3.org/1999/xlink"
38  xmlns:xi="http://www.w3.org/2001/XInclude"
39  xmlns:xhtml="http://www.w3.org/1999/xhtml"
40  xmlns:svg="http://www.w3.org/2000/svg"
41  xmlns:ns="http://docbook.org/ns/docbook"
42  xmlns:mathml="http://www.w3.org/1998/Math/MathML">
43  <title>Standard View Helper Library</title>
44 
45  <para>Should be autogenerated from the tags.</para>
46 </section>');
47  foreach ($classNames as $className) {
48  $this->generateXmlForClassName($className, $namespace, $xmlRootNode);
49  }
50  return $xmlRootNode->asXML();
51  }
52 
61  protected function generateXmlForClassName($className, $namespace, \SimpleXMLElement $xmlRootNode)
62  {
63  $reflectionClass = new \TYPO3\CMS\Extbase\Reflection\ClassReflection($className);
64  if (!$reflectionClass->isSubclassOf($this->abstractViewHelperReflectionClass)) {
65  return;
66  }
67  $tagName = $this->getTagNameForClass($className, $namespace);
68  $docbookSection = $xmlRootNode->addChild('section');
69  $docbookSection->addChild('title', $tagName);
70  $this->docCommentParser->parseDocComment($reflectionClass->getDocComment());
71  $this->addDocumentation($this->docCommentParser->getDescription(), $docbookSection);
72  $argumentsSection = $docbookSection->addChild('section');
73  $argumentsSection->addChild('title', 'Arguments');
74  $this->addArguments($className, $argumentsSection);
75  return $docbookSection;
76  }
77 
86  protected function addArguments($className, \SimpleXMLElement $docbookSection)
87  {
88  $viewHelper = $this->instanciateViewHelper($className);
89  $argumentDefinitions = $viewHelper->prepareArguments();
90  if (count($argumentDefinitions) === 0) {
91  $docbookSection->addChild('para', 'No arguments defined.');
92  return;
93  }
94  $argumentsTable = $docbookSection->addChild('table');
95  $argumentsTable->addChild('title', 'Arguments');
96  $tgroup = $argumentsTable->addChild('tgroup');
97  $tgroup['cols'] = 4;
98  $this->addArgumentTableRow($tgroup->addChild('thead'), 'Name', 'Type', 'Required', 'Description', 'Default');
99  $tbody = $tgroup->addChild('tbody');
100  foreach ($argumentDefinitions as $argumentDefinition) {
101  $this->addArgumentTableRow($tbody, $argumentDefinition->getName(), $argumentDefinition->getType(), $argumentDefinition->isRequired() ? 'yes' : 'no', $argumentDefinition->getDescription(), $argumentDefinition->getDefaultValue());
102  }
103  }
104 
111  protected function instanciateViewHelper($className)
112  {
113  return $this->objectManager->get($className);
114  }
115 
125  private function addArgumentTableRow(\SimpleXMLElement $parent, $name, $type, $required, $description, $default)
126  {
127  $row = $parent->addChild('row');
128  $row->addChild('entry', $name);
129  $row->addChild('entry', $type);
130  $row->addChild('entry', $required);
131  $row->addChild('entry', $description);
132  $row->addChild('entry', (string)$default);
133  }
134 
147  protected function addDocumentation($documentation, \SimpleXMLElement $docbookSection)
148  {
149  $splitRegex = '/^\\s*(=[^=]+=)$/m';
150  $regex = '/^\\s*(=([^=]+)=)$/m';
151  $matches = preg_split($splitRegex, $documentation, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
152  $currentSection = $docbookSection;
153  foreach ($matches as $singleMatch) {
154  if (preg_match($regex, $singleMatch, $tmp)) {
155  $currentSection = $docbookSection->addChild('section');
156  $currentSection->addChild('title', trim($tmp[2]));
157  } else {
158  $this->addText(trim($singleMatch), $currentSection);
159  }
160  }
161  }
162 
167  protected function addText($text, \SimpleXMLElement $parentElement)
168  {
169  $splitRegex = '/
170  (<code(?:.*?)>
171  (?:.*?)
172  <\\/code>)/xs';
173  $regex = '/
174  <code(.*?)>
175  (.*?)
176  <\\/code>/xs';
177  $matches = preg_split($splitRegex, $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
178  foreach ($matches as $singleMatch) {
179  if (preg_match($regex, $singleMatch, $tmp)) {
180  preg_match('/title="([^"]+)"/', $tmp[1], $titleMatch);
181  $example = $parentElement->addChild('example');
182  if (count($titleMatch)) {
183  $example->addChild('title', trim($titleMatch[1]));
184  } else {
185  $example->addChild('title', 'Example');
186  }
187  $this->addChildWithCData($example, 'programlisting', trim($tmp[2]));
188  } else {
189  $textParts = explode("\n", $singleMatch);
190  foreach ($textParts as $text) {
191  if (trim($text) === '') {
192  continue;
193  }
194  $this->addChildWithCData($parentElement, 'para', trim($text));
195  }
196  }
197  }
198  }
199 }