<?xml version="1.0"?>
<page-content>
<p>
<sectionList/>
</p>
<section id="sitegeneration" name="Site Generation" level="1"/>
<p>
There is classes <code>Page</code>, <code>PageFactory</code>, <code>SiteGenerator</code> and <code>PageRepository</code>.
</p>
<p>
Main class <code>SiteGenerator</code> and function <code>generate()</code>
he take from <code>PageRepository</code> by interface <code>IEnumeratePageId</code>
each <code>pageId</code> of site, and by this <code>pageId</code> take from
<code>PageFactory</code> object of class <code>Page</code>, and call method
<code>generate()</code> of class <code>Page</code>:
<source from="SiteGenerator.php"><![CDATA[
function generate(){
$this->pageRepository->pageIdEnumerator->reset();
while( $this->pageRepository->pageIdEnumerator->moveNext() ){
$id = $this->pageRepository->pageIdEnumerator->getElement();
$page = $this->pageFactory->getPageById( $id );
$page->generate();
}
}
]]></source>
</p>
<p>
But <code>PageFactory</code> return not <code>Page</code> <smile/>:
<source from="PageFactory.php"><![CDATA[
function getPageById( $id ){
switch ( $id ){
case 'fp':
$page = new PageFP();
break;
default:
$page = new PageSite( $id );
break;
}
return $page;
}
]]></source>
i.e. for <code>pageId = 'fp'</code> <code>PageFactory</code> return object of
<code>PageFP</code>, for other: <code>PageSite</code>.
</p>
<p>Some words about <code>PageRepository</code> he generate <code>pageIdArray</code>
from <code>pages.xml</code> by xslt transformation <code>pages2text.xsl</code>
(content/xslt/other/). But 'fp' dont exists in <code>pages.xml</code> it <code>pageId</code>
adds by hands:
<source from="PageRepository.php"><![CDATA[
function PageRepository(){
$this->pageIdEnumerator = new Enumerator();
$this->pageIdEnumerator->setElements( $this->pageIdArray );
$this->pageIdArray = $this->getPagesId(); // from xml file pages.xml
$this->pageIdArray[] = 'fp'; // add first page
}
]]></source>
</p>
<section id="pagegeneration" name="Page Generation" level="1"/>
<section id="pageshierarchy" name="Page class hierarchy" level="2"/>
<p>
There is hierarchy of pages:
<pre>
Page <- PageBase <- PageFP
<- PageSite
Page - abstract
PageBase - abstract
PageFP - first page of site
PageSite - any page of site
</pre>
Inheritance classes differs from <code>Page</code> only by constructor.
</p>
<p>
class Page makes next:
<ol>
<li>make self xml-content</li>
<li>make transformation by xslt</li>
<li>write result</li>
</ol>
</p>
<section id="makexml" name="Creating xml content" level="2"/>
<p>
Xml content are created by aggregation different xml sources.
</p>
<p>
xml-content start from
<source from="Page.php"><![CDATA[
$this->xml = '<?xml version="1.0"?'.'>'."\n";
$this->xml .= '<page-of-site>'."\n";
$this->xml .= '#add_elements_here#'."\n";
$this->xml .= '</page-of-site>'."\n";
]]></source>
</p>
<p>
Class <code>Page</code> contain array of objects of class <code>Element</code>.
They are added in constructors of inheritance classes (<code>PageBase</code>, <code>PageFP</code>, <code>PageSite</code>).
</p>
<p>
Function <code>makeXml()</code> are dead simple:
<source from="Page.php"><![CDATA[
function makeXml(){
foreach( $this->elements as $this->element ){
$this->element->makeContent();
$this->insertIntoXml();
}
}
]]></source>
</p>
<p>
Each object of class <code>Element</code> have attributes
<code>name</code> and <code>content</code>. And in function
<code>insertIntoXml()</code> by his <code>name</code>
xml-content-of-page are replaced by <code>content</code> of
<code>element</code>:
<source from="Page.php"><![CDATA[
function insertIntoXml(){
$name = '#'.$this->element->getName().'#';
$this->xml = str_replace(
$name, $this->element->getContent(), $this->xml
);
}
]]></source>
</p>
<p>
Hierarchy of elements:
<pre>
Element <- ElementFromFile
<- ElementFromText <- ElementForStub
<- ElementPageId
</pre>
By manipulation this elements perform creating xml-content-of-page.
</p>
<p>
F.e. class <code>PageBase</code> constructor:
<source><![CDATA[
function PageBase(){
$this->Page();
$this->elements[] = new ElementForStub(
array( 'params' => array( 'text' => "#common#\n#pages#\n#add_elements_here#\n" ) )
);
// #common#
$this->elements[] = new ElementFromFile(
array( 'name' => 'common', 'params' => array( 'fileName' => 'db-xml:common.xml' ) )
);
// #pages#
$this->elements[] = new ElementFromFile(
array( 'name' => 'pages', 'params' => array( 'fileName' => 'db-xml:pages.xml' ) )
);
}
]]></source>
Element <code>ElementForStub</code> replace <code>#add_elements_here#</code>,
then each next element replace self token: first <code>ElementFromFile</code>
replace <code>#common#</code> (which was added by previous
<code>ElementForStub</code> element),
second <code>ElementFromFile</code> replace <code>#pages#</code>
(note different between params passed in constructors).
</p>
<p>
Element <code>ElementFromFile</code> working with class <code>Content</code>
which have function <code>getContent()</code>:
<source from="Content.php"><![CDATA[
function getContent( $fileRequest ){
list( $area, $file ) = explode( ':', $fileRequest );
$fileName = $this->root . $area . '/' . $file;
$this->file->setFileName( $fileName );
$this->file->load();
return $this->file->getData();
}
]]></source>
where <code>$this->root</code> are path to <code>'content'</code> folder.
In that folder (if you remember) we have 3 folders (directories):
<code>db-xml</code>, <code>pages</code>, <code>xslt</code>.
</p>
<p>
And <code>$fileRequest</code> for function <code>getContent()</code>
are formed as <code>{area}:{fileName}</code>. F.e. if we want to get content of
file <code>pages.xml</code> in directory <code>db-xml</code>, we must make call:
<br/><code>$contentOfPagesXml = $objContent->getContent( 'xml:pages.xml' );</code>.
<br/>And by same manner to directory <code>pages</code> or <code>xslt</code>.
</p>
<p> And again about <code>PageBase</code>.</p>
<p>
As you may note element <code>ElementForStub</code> add token
<code>#add_elements_here#</code> in xml-content-of-page. This mean that
we have not finished xml-content. And we must to make inheritance from
this class.
</p>
<p>
Let's inheritance <code>PageFP</code> class. His constructor:
<source from="PageFP.php"><![CDATA[
function PageFP(){
$this->PageBase();
$this->pageId = 'index';
$this->elements[] = new ElementForStub(
array( 'params' => array( 'text' => "#page_content#\n#news#" ) )
);
// #page_content#
$this->elements[] = new ElementFromFile(
array( 'name' => 'page_content', 'params' => array( 'fileName' => 'pages:fp.xml' ) )
);
// #news#
$this->elements[] = new ElementFromFile(
array( 'name' => 'news', 'params' => array( 'fileName' => 'db-xml:news.xml' ) )
);
$this->xsltName = 'fp-page.xsl';
}
]]></source>
As you may note in this case element <code>ElementForStub</code>
(which replace token <code>#add_elements_here#</code>) dosnt have token
<code>#add_elements_here#</code>, i.e. in result we have finished xml-content.
</p>
<p>
xml-content will be contain files <code>pages/fp.xml</code>, <code>db-xml/news.xml</code>.
And xslt transformation will be made by <code>fp-page.xsl</code>.
</p>
<p>
For Page-package class <code>PageSite</code>, constructor:
<source from="PageSite.php"><![CDATA[
function PageSite( $pageId ){
$this->PageBase();
$this->pageId = $pageId;
$this->elements[] = new ElementForStub(
array( 'params' => array( 'text' => "#page_id#\n#page_content#\n" ) )
);
// #page_id#
$this->elements[] = new ElementPageId( $pageId );
// #page_content#
$this->elements[] = new ElementFromFile(
array( 'name' => 'page_content', 'params' => array( 'fileName' => 'pages:'.$pageId.'.xml' ) )
);
$this->xsltName = 'site-page.xsl';
}
]]></source>
Note that there is element <code>ElementPageId</code> which add tag <code><pageId></code>.
</p>
<p>After <code>makeXml()</code> we will have (i add comments):
<source from="result of makeXml()"><![CDATA[
<?xml version="1.0"?>
<page-of-site>
<!-- xml-header and 'page-of-site' are from Page -->
<!-- 'common' was added in PageBase -->
<!-- this is file '/content/db-xml/common.xml' -->
<common>
<year>2003</year>
<name>xmlSiteMaker</name>
<email>nemilya@mail.ru</email>
</common>
<!-- 'pages' was added in PageBase -->
<!-- this is file '/content/db-xml/pages.xml' -->
<pages>
<page id="123" name="Name" descr="Description"/>
...
</pages>
<!-- 'pageId' was added in PageSite -->
<!-- this parameter passed in constructor by PageFactory -->
<pageId>about</pageId>
<!-- 'page-content' was added in PageSite -->
<!-- this is file '/content/page/{pageId}.xml' -->
<page-content>
<p>
This application for offline generation.
From xml documents by xslt transformation.
</p>
<p>
<sectionList/>
</p>
...
</page-content>
</page-of-site>
]]></source>
</p>
<section id="maketransform" name="Make transform" level="2"/>
<p>
Each class <code>Page</code> have attribute <code>xsltName</code> by which
xml-content are transformed: <code>PageFP</code> - 'fp-page.xsl',
<code>PageSite</code> - 'site-page.xsl'. You can see this in constructor.
</p>
<section id="write" name="Write result" level="2"/>
<p>
For writing result there is class <code>PageWriter</code>. Class <code>Page</code>
in function <code>write()</code> call them:
<source from="Page.php"><![CDATA[
function writePage(){
echo "write page: {$this->pageId}\n";
$this->pageWriter->setContent( $this->page );
$this->pageWriter->setPageId( $this->pageId );
$this->pageWriter->write();
}
]]></source>
</p>
<section id="makeselfpage" name="Make Self Page Class" level="1"/>
<p>Of course you can write self class. Inheritance them from <code>Page</code>
or <code>PageBase</code>. And add to <code>PageFactory</code> in function
<code>getPageById</code> case for your <code>pageId</code>.
</p>
</page-content>
|