diff --git a/phpdotnet/phd/Package/Generic/XHTML.php b/phpdotnet/phd/Package/Generic/XHTML.php
index 7e3b1fcf..e3035c15 100644
--- a/phpdotnet/phd/Package/Generic/XHTML.php
+++ b/phpdotnet/phd/Package/Generic/XHTML.php
@@ -63,15 +63,6 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
'caution' => 'format_admonition',
'citation' => 'format_citation',
'citerefentry' => 'span',
- 'classname' => array(
- /* DEFAULT */ 'span',
- 'ooclass' => array(
- /* DEFAULT */ 'strong',
- 'classsynopsisinfo' => 'format_classsynopsisinfo_ooclass_classname',
- ),
- ),
- 'classsynopsis' => 'format_classsynopsis',
- 'classsynopsisinfo' => 'format_classsynopsisinfo',
'code' => 'code',
'collab' => 'span',
'collabname' => 'span',
@@ -157,22 +148,45 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
'note' => 'format_note',
'orgname' => 'span',
'othercredit' => 'format_div',
+ /** Class Synopsis related tags */
+ 'classsynopsis' => 'format_classsynopsis',
+ 'classsynopsisinfo' => 'format_classsynopsisinfo',
'ooclass' => array(
/* DEFAULT */ 'span',
- 'classsynopsis' => 'format_div',
+ 'classsynopsis' => 'format_classsynopsis_generic_oo_tag',
),
+ 'ooexception' => [
+ /* DEFAULT */ 'span',
+ 'classsynopsis' => 'format_classsynopsis_generic_oo_tag',
+ ],
'oointerface' => array(
/* DEFAULT */ 'span',
- 'classsynopsisinfo' => 'format_classsynopsisinfo_oointerface',
+ 'classsynopsis' => 'format_classsynopsis_generic_oo_tag',
+ 'classsynopsisinfo' => 'format_classsynopsisinfo_oointerface',
),
+ 'classname' => [
+ /* DEFAULT */ 'span',
+ 'ooclass' => [
+ /* DEFAULT */ 'span',
+ 'classsynopsis' => 'format_classsynopsis_ooclass_classname',
+ 'classsynopsisinfo' => 'format_classsynopsisinfo_ooclass_classname',
+ ],
+ ],
+ 'exceptionname' => [
+ /* DEFAULT */ 'span',
+ 'ooexception' => [
+ /* DEFAULT */ 'span',
+ 'classsynopsis' => 'format_classsynopsis_ooclass_classname',
+ ],
+ ],
'interfacename' => array(
/* DEFAULT */ 'span',
'oointerface' => array(
/* DEFAULT */ 'span',
+ 'classsynopsis' => 'format_classsynopsis_oointerface_interfacename',
'classsynopsisinfo' => 'format_classsynopsisinfo_oointerface_interfacename',
),
),
- 'exceptionname' => 'span',
'option' => 'format_option',
'orderedlist' => 'format_orderedlist',
'para' => array(
@@ -379,13 +393,29 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
/* DEFAULT */ false,
'fieldsynopsis' => 'format_fieldsynopsis_modifier_text',
),
- 'classname' => array(
- /* DEFAULT */ false,
- 'ooclass' => array(
+ /** Those are used to retrieve the class/interface name to be able to remove it from method names */
+ 'classname' => [
+ /* DEFAULT */ false,
+ 'ooclass' => [
/* DEFAULT */ false,
+ /** This is also used by the legacy display to not display the class name at all */
'classsynopsis' => 'format_classsynopsis_ooclass_classname_text',
- ),
- ),
+ ]
+ ],
+ 'exceptionname' => [
+ /* DEFAULT */ false,
+ 'ooexception' => [
+ /* DEFAULT */ false,
+ 'classsynopsis' => 'format_classsynopsis_oo_name_text',
+ ]
+ ],
+ 'interfacename' => [
+ /* DEFAULT */ false,
+ 'oointerface' => [
+ /* DEFAULT */ false,
+ 'classsynopsis' => 'format_classsynopsis_oo_name_text',
+ ]
+ ],
'methodname' => array(
/* DEFAULT */ false,
'constructorsynopsis' => array(
@@ -422,11 +452,14 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
protected $cchunk = array();
/* Default Chunk variables */
private $dchunk = array(
- "classsynopsis" => array(
- "close" => false,
- "classname" => false,
- "interface" => false, // bool: true when in interface
- ),
+ "classsynopsis" => [
+ "close" => false,
+ "classname" => false,
+ "interface" => false, // bool: true when in interface
+ "ooclass" => false,
+ "oointerface" => false,
+ "legacy" => true, // legacy rendering
+ ],
"classsynopsisinfo" => array(
"implements" => false,
"ooclass" => false,
@@ -896,6 +929,7 @@ public function format_refsect($open, $name, $attrs) {
return "\n";
}
+ /** Legacy rendering functions for class synopsis tags that wraps the definition in a class synopsis info tag */
public function format_classsynopsisinfo_oointerface($open, $name, $attrs) {
if ($open) {
if ($this->cchunk["classsynopsisinfo"]["ooclass"] === false) {
@@ -971,29 +1005,150 @@ public function format_classsynopsisinfo($open, $name, $attrs)
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"]) && $attrs[Reader::XMLNS_DOCBOOK]["role"] == "comment") {
return ' */';
}
+
+ assert($this->cchunk["classsynopsis"]["legacy"] === true);
$this->cchunk["classsynopsis"]["close"] = true;
return ' {';
}
- public function format_classsynopsis($open, $name, $attrs) {
+ /** This method is common between both legacy and new rendering for setting up the classname in the current chunk */
+ public function format_classsynopsis_ooclass_classname_text($value, $tag) {
+ /** If this is not defined this is the first ooclass/oointerface/ooexception and thus needs to
+ * set the class name to be able to remove it from the methods
+ */
+ if (!$this->cchunk["classsynopsis"]["classname"]) {
+ $this->cchunk["classsynopsis"]["classname"] = $value;
+ }
+ // Do not render outside ooclass class name in legacy rendering.
+ if ($this->cchunk["classsynopsis"]["legacy"]) {
+ return '';
+ }
+ return $this->TEXT($value);
+ }
+
+ /** Class synopsis rendering for new/better markup */
+ public function format_classsynopsis_oo_name_text($value, $tag) {
+ /** If this is not defined this is the first ooclass/oointerface/ooexception and thus needs to
+ * set the class name to be able to remove it from the methods
+ */
+ if (!$this->cchunk["classsynopsis"]["classname"]) {
+ $this->cchunk["classsynopsis"]["classname"] = $value;
+ }
+ return $this->TEXT($value);
+ }
+
+ public function format_classsynopsis_oointerface_interfacename($open, $name, $attrs, $props)
+ {
+ if ($this->cchunk["classsynopsis"]["legacy"] === true) {
+ return $this->transformFromMap($open, 'strong', $name, $attrs, $props);
+ }
+
if ($open) {
- // Think this just needs to be set on open and it will persist
- // Will remove comment after review
- if (
- isset($attrs[Reader::XMLNS_DOCBOOK]["class"]) &&
- $attrs[Reader::XMLNS_DOCBOOK]["class"] == "interface"
- ) {
- $this->cchunk["classsynopsis"]["interface"] = true;
+ /* If there has been a class prior this means that we are the first implementing interface
+ * thus mark the oointerface as already been rendered as the primary tag */
+ if ($this->cchunk["classsynopsis"]["ooclass"] === true) {
+ $this->cchunk["classsynopsis"]["oointerface"] = true;
}
+ /** Actual interface name in bold */
+ if ($this->cchunk["classsynopsis"]["oointerface"] === false) {
- return '
';
+ return 'interface ' . $this->transformFromMap($open, 'strong', $name, $attrs, $props);
+ }
+ /* Whitespace for next word */
+ return ' ';
+ }
+ /** Actual interface name in bold */
+ if ($this->cchunk["classsynopsis"]["oointerface"] === false) {
+ $this->cchunk["classsynopsis"]["oointerface"] = true;
+ return '';
}
+ /** We don't wrap extended interface in a tag */
+ if ($this->cchunk["classsynopsis"]['nb_list'] > 1) {
+ return ',';
+ }
+ return '';
+ }
+
+ public function format_classsynopsis_ooclass_classname($open, $name, $attrs, $props)
+ {
+ if ($this->cchunk["classsynopsis"]["legacy"] === true) {
+ return $this->transformFromMap($open, 'strong', $name, $attrs, $props);
+ }
+
+ if ($open) {
+ /** Actual class name in bold */
+ if ($this->cchunk["classsynopsis"]["ooclass"] === false) {
+ /** We force the name: parameter to 'classname' to not break CSS expectations for exceptionanme tags */
+ return 'class ' . $this->transformFromMap($open, 'strong', 'classname', $attrs, $props);
+ }
+ /* Whitespace for next word */
+ return ' ';
+ }
+ /** Actual class name in bold */
+ if ($this->cchunk["classsynopsis"]["ooclass"] === false) {
+ $this->cchunk["classsynopsis"]["ooclass"] = true;
+ return '';
+ }
+ /** We don't wrap extended class in a tag */
+ return '';
+ }
+
+ public function format_classsynopsis_generic_oo_tag($open, $name, $attrs, $props)
+ {
+ if ($this->cchunk["classsynopsis"]["legacy"] === true) {
+ return $this->transformFromMap($open, 'span', $name, $attrs, $props);
+ }
+
+ /* Close list of classes + interfaces by "opening" class def with { */
+ if (!$open) {
+ if (--$this->cchunk["classsynopsis"]['nb_list'] === 0) {
+ return ' {
';
+ }
+ }
+ return '';
+ }
+
+ public function format_classsynopsis($open, $name, $attrs, $props) {
+ $this->cchunk["classsynopsis"] = $this->dchunk["classsynopsis"];
+
+ /** Legacy presentation does not use the class attribute */
+ $this->cchunk["classsynopsis"]['legacy'] = !isset($attrs[Reader::XMLNS_DOCBOOK]["class"]);
+
+ if ($this->cchunk["classsynopsis"]['legacy']) {
+ if ($open) {
+ // Think this just needs to be set on open and it will persist
+ // Will remove comment after review
+ if (
+ isset($attrs[Reader::XMLNS_DOCBOOK]["class"]) &&
+ $attrs[Reader::XMLNS_DOCBOOK]["class"] == "interface"
+ ) {
+ $this->cchunk["classsynopsis"]["interface"] = true;
+ }
+
+ return '';
+ }
- if ($this->cchunk["classsynopsis"]["close"] === true) {
- $this->cchunk["classsynopsis"]["close"] = false;
+ /* Just always force the ending } to close the class as an opening { should always be present
+ if ($this->cchunk["classsynopsis"]["close"] === true) {
+ $this->cchunk["classsynopsis"]["close"] = false;
+ return "}
";
+ }
+ return "";
+ */
return "}";
}
- return "";
+
+ /* New rendering for more sensible markup:
+ * We open a fake classsynopsisinfo div to not break the CSS expectations */
+ if ($open) {
+ $occurrences = substr_count($props['innerXml'], '')
+ + substr_count($props['innerXml'], '')
+ + substr_count($props['innerXml'], '');
+ $this->cchunk["classsynopsis"]['nb_list'] = $occurrences;
+ return '';
+ } else {
+ return '}
';
+ }
}
public function format_classsynopsis_methodsynopsis_methodname_text($value, $tag) {
@@ -1018,10 +1173,6 @@ public function format_classsynopsis_methodsynopsis_methodname_text($value, $tag
return $method;
}
- public function format_classsynopsis_ooclass_classname_text($value, $tag) {
- $this->cchunk["classsynopsis"]["classname"] = $value;
- return $this->TEXT($value);
- }
public function format_fieldsynopsis($open, $name, $attrs) {
$this->cchunk["fieldsynopsis"] = $this->dchunk["fieldsynopsis"];
diff --git a/phpdotnet/phd/Package/PHP/XHTML.php b/phpdotnet/phd/Package/PHP/XHTML.php
index fdd2dee7..a1b42d33 100644
--- a/phpdotnet/phd/Package/PHP/XHTML.php
+++ b/phpdotnet/phd/Package/PHP/XHTML.php
@@ -7,13 +7,6 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML {
'appendix' => 'format_container_chunk',
'article' => 'format_container_chunk',
'book' => 'format_root_chunk',
- 'classname' => array(
- /* DEFAULT */ 'span',
- 'ooclass' => array(
- /* DEFAULT */ 'format_suppressed_tags',
- 'classsynopsisinfo' => 'format_classsynopsisinfo_ooclass_classname',
- ),
- ),
'chapter' => 'format_container_chunk',
'colophon' => 'format_chunk',
'function' => 'format_function',
@@ -90,15 +83,29 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML {
private $mytextmap = array(
'acronym' => 'format_acronym_text',
'function' => 'format_function_text',
- 'interfacename' => 'format_classname_text',
- 'exceptionname' => 'format_classname_text',
- 'classname' => array(
- /* DEFAULT */ 'format_classname_text',
- 'ooclass' => array(
- /* DEFAULT */ 'format_classname_text',
+ /** Those are used to retrieve the class/interface name to be able to remove it from method names */
+ 'classname' => [
+ /* DEFAULT */ 'format_classname_text',
+ 'ooclass' => [
+ /* DEFAULT */ 'format_classname_text',
+ /** This is also used by the legacy display to not display the class name at all */
'classsynopsis' => 'format_classsynopsis_ooclass_classname_text',
- ),
- ),
+ ]
+ ],
+ 'exceptionname' => [
+ /* DEFAULT */ 'format_classname_text',
+ 'ooexception' => [
+ /* DEFAULT */ 'format_classname_text',
+ 'classsynopsis' => 'format_classsynopsis_oo_name_text',
+ ]
+ ],
+ 'interfacename' => [
+ /* DEFAULT */ 'format_classname_text',
+ 'oointerface' => [
+ /* DEFAULT */ 'format_classname_text',
+ 'classsynopsis' => 'format_classsynopsis_oo_name_text',
+ ]
+ ],
'methodname' => array(
/* DEFAULT */ 'format_function_text',
'constructorsynopsis' => array(
@@ -708,8 +715,17 @@ public function format_grep_classname_text($value, $tag) {
}
public function format_classsynopsis_ooclass_classname_text($value, $tag) {
- /* intentionally not return the value, it will be printed out by
"soon" */
- parent::format_classsynopsis_ooclass_classname_text($value, $tag);
+ $content = parent::format_classsynopsis_ooclass_classname_text($value, $tag);
+ /** Legacy behaviour for crappy markup */
+ if ($content === '') {
+ return '';
+ }
+ return $this->format_classname_text($content, $tag);
+ }
+
+ public function format_classsynopsis_oo_name_text($value, $tag) {
+ $content = parent::format_classsynopsis_oo_name_text($value, $tag);
+ return $this->format_classname_text($content, $tag);
}
public function format_classname_text($value, $tag) {
diff --git a/phpdotnet/phd/Render.php b/phpdotnet/phd/Render.php
index 4117b4f4..a588dc99 100644
--- a/phpdotnet/phd/Render.php
+++ b/phpdotnet/phd/Render.php
@@ -72,8 +72,12 @@ public function execute(Reader $r) { /* {{{ */
$innerXml = "";
if (
- ($open && $r->name === "type") ||
- ($open && in_array($r->name, ["methodsynopsis", "constructorsynopsis", "destructorsynopsis"], true))
+ $open &&
+ (
+ $r->name === "type" ||
+ $r->name === "classsynopsis" ||
+ in_array($r->name, ["methodsynopsis", "constructorsynopsis", "destructorsynopsis"], true)
+ )
) {
$innerXml = $r->readInnerXml();
}
@@ -113,7 +117,7 @@ public function execute(Reader $r) { /* {{{ */
continue;
}
- if (strncmp($tag ?? '', "format_", 7) !== 0) {
+ if (/* !($tag instanceof \Closure) && */ !str_starts_with($tag ?? '', "format_")) {
$data = $format->transformFromMap($open, $tag, $name, $attrs, $props);
} else {
$data = $format->{$tag}($open, $name, $attrs, $props);