<?php
/*
* Class: ScBlock
* A page of sorts.
*
* Every comment block is defined as an `ScBlock`. A reader ([[ScReader]])
* will scan files, and for every comment block it encounters, it uses
* [[ScProject::register()]] to register a block instance to the project,
* which is created through [[factory()]].
*
* Each block has:
*
* - A block type
* - Title
* - Brief description (optional)
* - Content
* - Members
*
* Subclassing:
* This class provides a few protected methods. These methods are provided
* to be overridden for subclasses.
*
* [Filed under "API reference"]
*/
class ScBlock
{
// ========================================================================
// Factory
// ========================================================================
/*
* Function: factory()
* Creates an ScBlock instance with the right class as needed.
* [Static, grouped under "Factory"]
*/
function& factory($input, &$project, $the_classname = 'ScBlock')
{
$return = new $the_classname($input, $project);
$classname = $return->getTypeData('block_class');
if (!is_null($classname))
{ $returnx = new $classname($return, $project); return $returnx; }
return $return;
}
// ========================================================================
// ...
// ========================================================================
/*
* Constructor: ScBlock()
* The constructor. (Don't call)
*
* [Protected, grouped under "Protected methods"]
*/
function ScBlock($str, &$Project)
{
if (is_callable(array($str, 'getID')))
{
foreach ($str as $k => $v)
{ $this->{$k} = $v; }
return;
}
$this->Project =& $Project;
// Get the lines
$this->_data = $str;
$lines = str_replace(array("\r\n","\r"), array("\n","\n"), $str);
$this->_lines = explode("\n", $str);
// Check: the first line has to have a type
$title_line = $this->_lines[0];
if (strpos($title_line, ':') === FALSE) { return; }
// Get the type keyword.
// For instance, in ("Class: MyClass"), it's 'class'
// Then check if it exists in the defined type_keywords
$type_str = trim(substr($title_line, 0, strpos($title_line, ':')));
$this->title = trim(substr($title_line, strpos($title_line, ':')+1, 99999));
$this->typename = $type_str;
$type_str = trim(strtolower($type_str));
$this->_lines = array_slice($this->_lines, 1);
// Check: the first line has to have a *valid* type
if (!in_array($type_str, array_keys($Project->options['type_keywords'])))
{ return; }
$this->type = $Project->options['type_keywords'][$type_str];
$td = $this->getTypeData();
// Find the tag hash
// TODO: 'All below'
foreach ($this->_lines as $i => $line)
{
preg_match('~^\[(.*?)\]$~', $line, $m);
if (count($m) > 0)
{
$match = $m[count($m)-1];
$this->parseTag($match);
array_splice($this->_lines, $i, 1, array());
break;
}
}
// Trim trailing blank lines
while (count($this->_lines) > 0)
{
if (trim($this->_lines[0]) != '') { break; }
array_splice($this->_lines, 0, 1, array());
}
// If it can have a brief
if ((isset($td['has_brief'])) && ($td['has_brief'] == TRUE) &&
((!isset($this->_skip_brief)) || (!$this->_skip_brief)))
{
// Look for a blank line
$offset = array_search('', $this->_lines);
if ($offset !== FALSE)
{
// Break at the first blank line
$this->brief = array_slice($this->_lines, 0, $offset);
$this->brief = $this->toHTML($this->brief);
$this->_lines = array_slice($this->_lines, $offset+1);
} else {
// Everything is a brief description
$this->brief = $this->toHTML($this->_lines);
$this->_lines = array();
}
}
$this->content = $this->toHTML($this->_lines);
$this->valid = TRUE;
if (is_null($this->_order))
{ $this->_order = (int) $td['default_order']; }
unset($this->_lines);
unset($this->_data);
}
function unregister()
{
/* Function: unregister()
* Removes the block from the tree.
*/
$descendants =& $this->getDescendants();
// Remove it from 'blocks'
foreach ($this->Project->data['blocks'] as $key => &$block)
if ($block->getID() == $this->getID())
{ unset($this->Project->data['blocks'][$key]); break; }
foreach ($this->Project->data['tree'] as $key => &$block)
if ($block->getID() == $this->getID())
{ unset($this->Project->data['tree'][$key]); break; }
// Remove it from parent's member list.
$parent =& $this->getParent();
if (!is_null($parent))
foreach ($parent->_children as $id => &$child)
if ($child->getID() == $this->getID())
{ unset($parent->_children[$id]); break; }
foreach ($descendants as &$grandchild)
{ $grandchild->unregister(); }
}
function parseTag($tags)
{
/* Function: parseTag()
* Parses a tag (A delegate task of [[ScBlock()]]).
*
* Usage:
* $block->parseTag($tag_line)
* (Don't call this function.)
*
* Parameters:
* $tag_line - The line; the text inside the `[` and `]` brackets
*
* Description:
* This function parses out a tag line in the comment block
* (e.g., `[read-only, private]`). It will then set [[$_tags]] and other
* effects as needed. It is called by the [[ScBlock()]] constructor
* during the process of parsing the comment block.
*
* You may override this function parse out special commands from the
* tag line (`[...]`) blocks.
*
* Returns:
* Nothing; this function will do things (set groups, add tags, etc)
* in place. Specifically, it will set:
*
* - $this->_group ("grouped under ...")
* - $this->_supposed_parent ("filed under ...")
* - $this->_inherit_parent ("inherits ...")
* - $this->_order ("priority #")
* - $this->_skip_brief ("No brief")
* - $this->_skip_member_list ("Skip member list")
* - $this->_tags (everything else)
*/
// Input looks like: "read-only, grouped under mygroup, private"
$tag_list = array_map('trim', explode(',', $tags));
$valid_tags = array_keys($this->Project->options['tags']);
$vtags = $this->getValidTags();
foreach ($tag_list as $tag)
{
// Match:
// - [In [the]] group X
// - [[filed] under [the]] group X
// - Group[ed [under]] X
// - Group X
preg_match('~^(?:in (?:the )?|(?:(?:filed )?under (?:the )?))?group(?:ed(?: under)?)? (?:")?(.*?)(?:")?$~i',
$tag, $m);
if (count($m) > 0)
{
$this->_group = $m[count($m)-1];
continue;
}
// Filed under ...
preg_match('~^(?:filed )?under(?: the (?:.*?))? (?:")?(.*?)(?:")?$~i',
$tag, $m);
if (count($m) > 0)
{
$parent_keyword = $m[count($m)-1];
$this->_supposed_parent = $parent_keyword;
continue;
}
// Inherits/extends ...
preg_match('~^(?:inherits|extends) (?:")?(.*?)(?:")?$~i',
$tag, $m);
if (count($m) > 0)
{
$parent_keyword = $m[count($m)-1];
$this->_inherit_parent = $parent_keyword;
continue;
}
// Order #x...
preg_match('~^(?:sort )?(?:order|priority|order priority) (?:#)?(.*?)$~i', $tag, $m);
if (count($m) > 0)
{
$this->_order = (int) $m[count($m)-1];
continue;
}
// No brief
preg_match('~^(?:no|skip) (?:intro|introduction|brief|introductory(?: (?:paragraph|(?:desc(?:ription)))?)?)?$~i',
$tag, $m);
if (count($m) > 0)
{
$this->_skip_brief = 1;
continue;
}
// No member list
preg_match('~^(?:no|skip) (?:the )?(?:members? list)?$~i',
$tag, $m);
if (count($m) > 0)
{
$this->_skip_member_list = 1;
continue;
}
$tag = strtolower($tag);
if (in_array($tag, array_keys($vtags)))
{ $this->_tags[] = $vtags[$tag]; }
}
}
/*
* Function: getValidTags()
* Returns a list of valid tags in associative array format.
*
* Description:
* This function returns a thesaurus of sorts as key-value pairs. The
* keys are the valid tag names (including synonyms), and the values
* associated with them are what they are a synonym for.
*
* Array
* (
* "deprecated" => "deprecated",
* "deprec" => "deprecated",
* "read-only" => "read-only",
* "readonly" => "read-only",
* )
*
* See also:
* [[getTags()]]
* : To retrieve the actual tags defined for the block
*
* [[hasTags()]]
* : To check if the there are tags defined
*
* [Grouped under "Tag functions"]
*/
function getValidTags()
{
$vtags = array();
// Combine the project-wide tags and blocktype-specific tags...
foreach (array_merge($this->Project->options['tags'], $this->getTypeData('tags')) as $tag)
{ $vtags[$tag] = $tag; }
// And it's synonyms...
$synonyms =& $this->Project->options['tag_synonyms'];
foreach ($vtags as $vtag)
{
if (isset($synonyms[$vtag]))
{
$aliases = (array) $synonyms[$vtag];
foreach ($aliases as $alias)
{ $vtags[$alias] = $vtag; }
}
}
// Into the valid tags
return $vtags;
}
/*
* Function: hasTags()
* Checks if the current block has tags defined.
*
* Usage:
* $this->hasTags()
*
* Returns:
* `TRUE` or `FALSE`.
*
* See also:
* [[getTags()]]
* : To retrieve the actual tags
*
* [[getValidTags()]]
* : To check what tags the block is allowed to have
*
* [Grouped under "Tag functions"]
*/
function hasTags($p = NULL)
{
return (count($this->_tags) > 0) ? TRUE : FALSE;
}
/*
* Function: getTags()
* Returns the tags for the block.
*
* Usage:
* $block->getTags()
*
* Description:
* For the descriptions that containing tag lines (in the format
* `[Private, read-only]`), this function will return those tags associated
* with the blocks, which in the example is *private* and *read-only*.
*
* The tags allowed for any block is defined in it's `block_types`
* definition in the configuration, and in the project's configuration
* for `tags`.
*
* Tag synonyms defined in the configuration (`tag_synonyms`) are also
* taken into account. For instance, if a description contains `[readonly]`
* and *readonly* is considered as a synonym for *read-only*, the tag
* that will be returned will be `read-only`.
*
* Returns:
* An array of tag strings.
*
* Example:
* This example will retrieve tags.
*
* echo "Tags for the home page:\n";
* foreach ($Project->data['home']->getTags() as $tag)
* { echo "- $tag\n"; }
*
* Possible output:
*
* Tags for the home page:
* - deprecated
* - private
*
* See also:
* [[hasTags()]]
* : To check if the there are tags defined for the block
* (equivalent to `count(getTags()) > 0`)
*
* [[getValidTags()]]
* : To check what tags the block is allowed to have
*
* [Grouped under "Tag functions"]
*/
function getTags()
{
return $this->_tags;
}
/*
* Function: getGroup()
* Returns the group where the block belongs to.
*
* Usage:
* $this->getGroup()
*
* Description:
* For the descriptions that contain `[Grouped under "My group name"]`
* lines, this will return the group for the current block (which in the
* example is "My group name").
*
* Returns:
* NULL of no group, otherwise a string of the group
*/
function getGroup()
{
return $this->_group;
}
/*
* Function: isHomePage()
* Checks if the current block is the home page.
*
* Usage:
* $block->isHomePage()
*
* Description:
* The home page block is defined as the one having the same title as
* the `name` defined in the configuration. For instance, if `name` is
* set to "SourceScribe manual", having a page with that name will
* automatically assign that to be a homepage.
*
* An empty home page will be created if there is none defined.
*
* Home page blocks always have the ID of `index`, as you can find out
* with [[getID()]].
*
* Returns:
* `TRUE` if the block is the homepage block, otherwise `FALSE`.
*/
function isHomePage()
{
if ($this->title == $this->Project->getName()) { return TRUE; }
return FALSE;
}
// ========================================================================
// Group: Content methods
// [All below are grouped under "Content methods"]
// ========================================================================
/*
* Function: getContent()
* Returns the content of the block in HTML format.
*
* Description:
* This also consults the virtual (overridable) functions
* [[getPreContent()]] and [[getPostContent()]] before returning the
* final output.
*
* See also:
* - [[getPreContent()]]
* - [[getPostContent()]]
*
* [Grouped under "Data functions"]
*/
function getContent()
{
return $this->getPreContent() . $this->content . $this->getPostContent();
}
/*
* Function: hasContent()
* Checks if the block has content.
* [Grouped under "Data functions"]
*/
function hasContent()
{
return (trim((string) $this->content) == '') ? FALSE : TRUE;
}
/*
* Function: getPreContent()
* Virtual function that lets subclasses make content before the content.
*
* See also:
* - [[getContent()]]
* - [[getPostContent()]]
*
* [Protected, grouped under "Protected methods"]
*/
function getPreContent()
{
return '';
}
/*
* Function: getPostContent()
* Virtual function that lets subclasses make content after the content.
*
* See also:
* - [[getContent()]]
* - [[getPreContent()]]
*
* [Protected, grouped under "Protected methods"]
*/
function getPostContent()
{
return '';
}
/*
* Function: getTitle()
* TBD
* [Grouped under "Data functions"]
*/
function getTitle()
{
$title = $this->title;
$pre = $this->getTypeData('title_prefix');
if ((is_string($pre)) &&
(strtolower(substr($title, 0, strlen($pre))) !=
strtolower($pre)))
{ $title = $pre . $title; }
$suf = $this->getTypeData('title_suffix');
if ((is_string($suf)) &&
(strtolower(substr($title, strlen($title)-strlen($suf), strlen($suf))) !=
strtolower($suf)))
{ $title = $title . $suf; }
return
$title;
}
/*
* Function: getLongTitle()
* Returns a long title.
* [Grouped under "Data functions"]
*/
function getLongTitle()
{
$f = array();
if ($this->hasParent())
{
$parent = $this->getParent();
$f[] = $parent->getTitle() . ' ->';
}
$f[] = $this->getTitle();
return implode(' ', $f);
}
/*
* Function: getKeyword()
* Returns the keyword for searching
* [Grouped under "Data functions"]
*/
function getKeyword()
{
return $this->title;
}
/*
* Function: getBrief()
* TBD
* [Grouped under "Data functions"]
*/
function getBrief()
{
return $this->brief;
}
/*
* Function: getType()
* Returns the typename.
*
* Usage:
* $this->getType()
*
* Description:
* This returns the actual type, not the synonym used. For instance,
* a "Constructor: myclass()" block may return a type of `function`
* instead of 'constructor'. If you would like to see that instead
* (e.g., "constructor"), use [[getTypeName()]].
*
* Returns:
* A string of the typename.
*
* See also:
* - [[getTypeName()]]
*
* [Grouped under "Block type functions"]
*/
function getType()
{
return $this->type;
}
/*
* Function: getTypeName()
* Returns the type name as shown in the first line.
*
* [Grouped under "Block type functions"]
*/
function getTypeName()
{
return $this->typename;
}
/*
* Function: getTypeData()
* Returns the data for the type in the class, as defined
* in [[Scribe::$Options]].
*
* [Grouped under "Block type functions"]
*/
function getTypeData($p = NULL)
{
global $Sc;
if (!isset($this->Project->options['block_types'])) { return; }
if (!isset($this->Project->options['block_types'][(string) $this->type])) { return; }
$type = $this->Project->options['block_types'][(string) $this->type];
if (is_string($p)) {
if (isset($type[$p])) { return $type[$p]; }
else { return NULL; }
}
return $type;
}
/*
* Function: getID()
* Returns the unique ID string for this node.
* [Grouped under "Data functions"]
*/
function getID()
{
if (($this->isHomePage()) && (is_null($this->_id)))
{ $this->_id = 'index'; return 'index'; }
elseif (is_null($this->_id))
{
// Initialize
$id_tokens = array();
$parent =& $this->getParent();
$td = $this->getTypeData();
// Add the parent as another suffix, if we want it there
if ((isset($td['parent_in_id'])) &&
(is_callable(array($parent, 'getTypeData'))) &&
(in_array(strtolower($parent->type), $td['parent_in_id'])))
{
$id_tokens[] = $this->_toID($parent->title);
}
// Add a suffix of the abbreviation of the type
// (e.g., "function" => "fn")
if ((isset($td['short'])) && ($td['short'] != ''))
{ $id_tokens[] = $this->_toID($td['short']); }
// Add our own title, and finalize
$id_tokens[] = $this->_toID($this->title);
$this->_id = implode('.', $id_tokens);
return $this->_id;
}
return $this->_id;
}
/* ======================================================================
* Protected methods
* ====================================================================== */
/*
* Function: _toID()
* Converts a string input (usually the title) into an ID.
*
* [Protected, Grouped under "Protected methods"]
*/
function _toID($p, $limit=128, $underscore = '', $lower = FALSE)
{
preg_match_all('/[^a-zA-Z0-9]+|(.)/',$p, $m);
$ff = ''; $f = '';
foreach ($m[1] as $ch) { $ff .= ($ch != '') ? $ch : ' '; }
//foreach (explode(' ', trim($ff)) as $word)
// { $f .= strtoupper(substr($word,0,1)) . (substr($word,1)); }
$f = str_replace(' ', '_', trim($ff));
return substr($f, 0, $limit);
}
/*
* Function: toHTML()
* Processes plaintext (ripped from the source files) and converts them
* to HTML.
*
* Description:
* This relies on the Markdown library to parse out the content.
*
* [Protected, grouped under "Protected methods"]
*/
function toHTML($lines)
{
if (is_array($lines)) { $str = implode("\n", $lines); }
else { $str = (string) $lines; }
// Convert "Usage:" to H2's
$str = preg_replace('~(?:^|\\r|\\n)([A-Za-z0-9\- ]+):[\\r\\n]~sm',
"\n## \\1\n\n", $str);
// Convert to dl/dt/dd
$str = preg_replace('~ *([\[\]\(\)/a-zA-Z0-9\-`_\$\.\\\'"\*]+) +- (.*?)([\\r\\n$])~s',
"\n\\1\n: \\2\\3", $str);
// Convert [[]] links
$str = preg_replace('~\[\[(.*?)\]\]~s', "<a href=\"##\\1\">\\1</a>", $str);
// return '<pre>' . htmlentities($str) . '</pre>';
$str = markdown($str);
// Wrap heading texts inside span elements
$str = preg_replace('~(<h[1-6]>)(.*?)(</h[1-6]>)~s',
'\\1<span>\\2</span>\\3', $str);
// Wrap DTs inside span elements
foreach (array('dt' => 'term',
'dd' => 'definition')
as $tag => $classname)
{
$str = preg_replace("~(<$tag>)(.*?)(</$tag>)~s",
'\\1<span class="'.$classname.'">\\2</span>\\3', $str);
}
return $str;
}
function finalize()
{
/* Function: finalize()
* Ran when building is done.
*
* Usage:
* $block->finalize()
* (Don't call this function.)
*
* Description:
* You may override this to do more post-build actions for the block.
*
* [Protected, grouped under "Protected methods"]
*/
// Sort by order priority
usort($this->_children, array(&$this, '_sortChildren'));
// Subgroups
foreach ($this->_children as &$child_block)
{
$group = $child_block->getGroup();
if (is_null($group)) { $group = $child_block->getTypeData('title_plural'); }
// Initialize the group if it hasn't been yet
if (!isset($this->_subgroups[$group]))
{
$this->_subgroups[$group] = array(
'title' => $group,
'members' => array()
);
}
$this->_subgroups[$group]['members'][] =& $child_block;
}
}
function _sortChildren($a, $b)
{
if ($a == $b) { return 0; }
$ap = (int) $a->_order;
$bp = (int) $b->_order;
// To preserve order
if ($ap == $bp) {
$parent = $a->getParent();
foreach ($parent->getChildren() as $child) {
if ($child == $a) { return -1; }
if ($child == $b) { return 1; }
}
return 0;
}
return ($ap > $bp) ? -1 : 1;
}
function preFinalize()
{
// Filed under
if ((!$this->hasParent()) && (!is_null($this->_supposed_parent)))
{
// Found a "Filed under", now look up it's supposed parent and
// put them there
$results =& $this->Project->lookup($this->_supposed_parent, $this);
if (count($results) > 0)
{
$results[0]->registerChild($this);
// Remove from tree
foreach ($this->Project->data['tree'] as $id => &$item)
if ($item == $this)
{ unset($this->Project->data['tree'][$id]); break; }
}
}
// Inherit
$this->_doInheritance();
}
function _doInheritance()
{
if (!is_null($this->_inherit_parent))
{
// Found a "Inherits", now duplicate the children of it's
// "parent class" and add it to this
$results =& $this->Project->lookup($this->_inherit_parent, $this);
if (count($results) > 0)
{
// Make sure the parent's inheritances are resolved before
// we continue
$results[0]->_doInheritance();
// This next line will duplicate the children SUPPOSEDLY
$childrenx = $results[0]->getChildren();
$children = array();
foreach ($childrenx as $child)
{ $children []= _clone($child); }
foreach ($children as &$child)
{
// If there's already something with the same name, norget it
foreach ($this->getChildren() as $other_child)
{
if (($other_child->getType() == $child->getType()) &&
($other_child->getTitle() == $child->getTitle()))
{ continue 2; }
}
$child->_tags[] = 'inherited';
// Add to subgroups and children
$this->registerChild($child);
// Cheap version of ScProject::register()
$this->Project->data['blocks'][] =& $child;
}
}
}
}
function registerChild(&$child_block)
{
/* Function: registerChild()
* Registers a block as a child of this block.
*
* Usage:
* > $block->registerChild($child)
*
* Parameters:
* $child - (ScBlock) The child.
*
* Description:
* This is called by [[ScProject::register()]]. The block passed onto
* this function should be already fully initialized.
*
* Returns:
* Nothing.
*
* [Protected, grouped under "Protected methods"]
*/
// Register to children and parent
$this->_children[] =& $child_block;
$child_block->_parent =& $this;
// Reset the ID so it can be recomputed according to the new parent
$child_block->_id = NULL;
return;
}
/* ======================================================================
* Traversion functions
* ====================================================================== */
/*
* Function: getChildren()
* Returns the list of children.
*
* Usage:
* Array $block->getChildren()
*
* Returns:
* An array of [[ScBlock]] instances.
*
* [Grouped under "Traversion functions"]
*/
function& getChildren()
{
return $this->_children;
}
function& getDescendants()
{
$return = array();
$descendants = array();
$i = 0;
foreach ($this->_children as &$child)
{
$return[] =& $child;
$descendants[$i] =& $child->getDescendants();
foreach ($descendants[$i] as &$subchild)
{ $return[] =& $subchild; }
$i++;
}
return $return;
}
/*
* Function: hasChildren()
* Checks if the block has children.
*
* [Grouped under "Traversion functions"]
*/
function hasChildren()
{
return (count($this->_children) > 0) ? TRUE : FALSE;
}
/*
* Function: getParent()
* Returns the parent block, or `NULL` if none.
*
* [Grouped under "Traversion functions"]
*/
function& getParent()
{
$return = NULL;
# No parent for home mpage
if ($this->isHomePage())
{ return $return; }
if ((is_callable(array($this->_parent, 'getID'))) &&
($this->_parent != $this))
{ $return = $this->_parent; }
else
{ $return = NULL; }
return $return;
}
/*
* Function: getAncestry()
* Returns all the parent nodes.
*
* Usage:
* ScBlock $block->getAncestry([$options])
*
* Description:
* Options can be defined as an associative array. All of these are
* optional.
*
* exclude_home - If the home page is to be excluded
* include_this - If this block is to be included
*
* Returns:
* An array of parent [[ScBlock]] instances. The last item will be
* the immediate parent, and the first item will be the most senior
* grandparent (i.e., home page).
*
* Example:
*
* The output of this function would often look similar to this format.
*
* array(
* ScBlock(..), // Home
* ScBlock(..), // Class MyClass
* ScBlock(..), // myFunction()
* );
*
* [Grouped under "Traversion functions"]
*/
function& getAncestry($options = array())
{
$options = (array) $options;
$block = $this;
$f = array();
$i = 0;
$blocks = array();
if ((isset($options['include_this'])) && ($options['include_this']))
{
if ((!$this->isHomePage()) || (!isset($options['exclude_home']))
|| (!$options['exclude_home']))
{ $f[] =& $this; }
}
while (TRUE) {
if (!$block->hasParent()) { break; }
$parent =& $block->getParent();
// Exclude the home page if we're asked to
if ((!$parent->hasParent()) && (isset($options['exclude_home']))
&& ($options['exclude_home']))
{ break; }
$blocks[$i] =& $block->getParent();
array_unshift($f, &$blocks[$i]);
$block =& $blocks[$i++];
}
return $f;
}
/*
* Function: hasParent()
* Checks if the current block has a parent.
* [Grouped under "Traversion functions"]
*/
function hasParent()
{
return (is_null($this->getParent())) ? FALSE : TRUE;
}
/*
* Function: getMemberLists()
* Returns a grouped list of member items under the block.
*
* Usage:
* $this->getMemberLists()
*
* Description:
* This is used by outputs to list down the members of a class
* (or any other block with children).
*
* Example:
* var_dump($block->getMemberLists());
*
* Possible output:
*
* array
* (
* 'properties' => array
* (
* 'title' => 'Member properties',
* 'members' => array( ScBlock, ScBlock, ScBlock, ... )
* ),
* 'methods' => array
* (
* <same as above>
* ),
* ...and so on
* )
*
* Returns:
* Unspecified.
*
* [Grouped under "Traversion functions"]
*/
function& getMemberLists()
{
return $this->_subgroups;
/*
$f = array();
foreach ($this->getChildren() as $node)
{
$type = $node->getType();
if (!isset($f[$type]))
{
$f[$type] = array();
$f[$type]['title'] = 'Member ' . $type . 's';
$f[$type]['members'] = array();
}
$f[$type]['members'][] = $node;
}
return $f;*/
}
/* ======================================================================
* Private properties
* ====================================================================== */
/*
* Property: $Project
* Reference to the parent [[ScProject]] instance.
*/
var $Project;
var $_data;
var $valid = FALSE;
/* Property: $typename
* The name of the type as defined in the first line.
* [Private]
*/
var $typename = '';
/*
* Property: $type
* The proper name of the type.
*
* Description:
* Access the type of the block through [[getType()]]
* and [[getTypeData()]].
*
* [Private]
*/
var $type;
/*
* Property: $title
* The raw title of the block.
*
* Description:
* This is a read-only property. To get the title, use [[getTitle()]] as
* it will provide additional stuff.
*
* [Private]
*/
var $title;
/*
* Property: $content
* The content in HTML format, as already parsed by [[toHTML()]].
*
* [Private]
*/
var $content;
/*
* Property: $brief
* The brief description in HTML format.
*
* [Private]
*/
var $brief;
/*
* Property: $_id
* The ID.
*
* Description:
* Access the ID of the block through [[getID()]]. The ID is
* automatically-determined; it can not be user-set.
*
* [Private]
*/
var $_id = null;
/* Property: $_group
* The group.
*
* Description:
* Access via [[getGroup()]], or the parent's [[getMemberLists()]].
*
* [Private]
*/
var $_group = NULL;
/*
* Property: $_parent
* Reference to the parent in the index tree.
*
* Description:
* This is a private variable only used by the `ScBlock` class.
*
* - To get the parent of the block, use [[getParent()]].
* - To get all it's parents, use [[getAncestry()]].
* - To register a block as a child of another block,
* use [[registerChild()]].
*
* See also:
* - [[getParent()]]
* - [[getChildren()]]
* - [[registerChild()]]
*
* [Private]
*/
var $_parent;
/*
* Property: $_children
* An array of references to `ScBlock` instances that are the children of
* the current block.
*
* Description:
* This is a private variable only used by the `ScBlock` class.
*
* - To get the children of the block, use [[getChildren()]].
* - To get the children in a grouped manner, use [[getMemberLists()]].
* - To register a block as a child of another block,
* use [[registerChild()]].
*
* See also:
* - [[getParent()]]
* - [[getChildren()]]
* - [[registerChild()]]
*
* [Private]
*/
var $_children = array();
/*
* Property: $_tags
* Tags. Please use [[getTags()]] instead
* [Private]
*/
var $_tags = array();
/*
* Property: $_subgroups
* Subgroups.
*
* Example:
* See [[getMemberLists()]] for an example of the data.
*
* [Private]
*/
var $_subgroups = array();
/*
* Property: $_supposed_parent
* Used by finalize
*/
var $_supposed_parent = NULL;
/*
* Property: $_inherit_parent
* Used by finalize
*/
var $_inherit_parent = NULL;
/*
* Property: $_skip_member_list
* Used by finalize
*/
var $_skip_member_list = NULL;
/*
* Property: $_order
* Used by finalize
*/
var $_order = NULL;
/* ======================================================================
* End
* ====================================================================== */
}
class ScClassBlock extends ScBlock
{
function getTitle()
{
return 'Class ' . $this->title;
}
}