diff --git a/README.md b/README.md
index 44a384b..e363fc7 100644
--- a/README.md
+++ b/README.md
@@ -224,14 +224,15 @@ name is generated by appending "_rdf" to your model name.
Inside the createphp tag, you can render the entity with the default structure
(see above), or render single fields as in the example below:
- {% createphp mymodel %}
-
+ {% createphp mymodel noautotag %}
+
{{ createphp_content( mymodel_rdf.title ) }}
{{ mymodel_rdf.content|raw }}
{% endcreatephp %}
-You need to render the attributes of the entity in a tag that encloses all of
+With ``noautotag`` the enclosing elements are not rendered automatically. Therefore,
+you need to render the attributes of the entity in a tag that encloses all of
your entity. Inside that tag, you can place arbitrary HTML and render single
fields or render attributes and content of the fields separately for closer
control over the generated HTML.
diff --git a/src/Midgard/CreatePHP/Entity/Collection.php b/src/Midgard/CreatePHP/Entity/Collection.php
index 9a3d8ac..6c406d4 100644
--- a/src/Midgard/CreatePHP/Entity/Collection.php
+++ b/src/Midgard/CreatePHP/Entity/Collection.php
@@ -230,6 +230,19 @@ public function renderStart($tag_name = false)
return parent::renderStart($tag_name);
}
+ /**
+ * {@inheritDoc}
+ *
+ * Overwrite to not output about attribute again if parent is rendering
+ */
+ public function renderAttributes(array $attributesToSkip = array())
+ {
+ if ($this->_parent && $this->_parent->isRendering()) {
+ $attributesToSkip[] = 'about';
+ }
+ return parent::renderAttributes($attributesToSkip);
+ }
+
/**
* {@inheritDoc}
*
diff --git a/src/Midgard/CreatePHP/Extension/Twig/CreatephpNode.php b/src/Midgard/CreatePHP/Extension/Twig/CreatephpNode.php
index 2b69767..3d6554b 100644
--- a/src/Midgard/CreatePHP/Extension/Twig/CreatephpNode.php
+++ b/src/Midgard/CreatePHP/Extension/Twig/CreatephpNode.php
@@ -29,17 +29,22 @@ class CreatephpNode extends Twig_Node
* @param Twig_NodeInterface $body The body node
* @param string $modelname The name of the model class to make an rdfa entity
* @param string $varname The name for the rdfa entity to expose
+ * @param boolean $autotag Automatically render start and end part of the node?
* @param integer $lineno The line number
* @param string $tag The tag name
*/
- public function __construct(Twig_NodeInterface $body, $modelname, $varname, $lineno = 0, $tag = null)
+ public function __construct(Twig_NodeInterface $body, $modelname, $varname, $autotag, $lineno = 0, $tag = null)
{
$nodes = array('body' => $body);
if (empty($varname)) {
$varname = $modelname . '_rdf';
}
- $attributes = array('varname' => $varname, 'modelname' => $modelname);
+ $attributes = array(
+ 'varname' => $varname,
+ 'modelname' => $modelname,
+ 'autotag' => $autotag
+ );
parent::__construct($nodes, $attributes, $lineno, $tag);
}
@@ -59,9 +64,38 @@ public function compile(Twig_Compiler $compiler)
$compiler
->raw(";\n")
+ ;
+
+ //output opening and closing elements for this node?
+ $autotag = $this->getAttribute('autotag');
+ if ($autotag) {
+ $compiler->write('echo ');
+ }
+
+ /**
+ * To set the node into the correct mode, start rendering even if no
+ * output is needed. It is up to the user to be intelligent enough to
+ * understand what he has to do if he is using noautotag.
+ */
+ $compiler
+ ->write('$context[')
+ ->repr($this->getAttribute('varname'))
+ ->write(']->renderStart()')
+ ->raw(";\n");
+
+ $compiler
->subcompile($this->getNode('body'))
;
+ if ($autotag) {
+ $compiler->write('echo ');
+ }
+ $compiler
+ ->write('$context[')
+ ->repr($this->getAttribute('varname'))
+ ->write(']->renderEnd()')
+ ->raw(";\n");
+
$compiler
->write('unset($context[')
->repr($this->getAttribute('varname'))
diff --git a/src/Midgard/CreatePHP/Extension/Twig/CreatephpTokenParser.php b/src/Midgard/CreatePHP/Extension/Twig/CreatephpTokenParser.php
index 18096eb..e4ae2df 100644
--- a/src/Midgard/CreatePHP/Extension/Twig/CreatephpTokenParser.php
+++ b/src/Midgard/CreatePHP/Extension/Twig/CreatephpTokenParser.php
@@ -49,15 +49,20 @@ public function parse(Twig_Token $token)
$var = $stream->expect(Twig_Token::STRING_TYPE)->getValue();
}
+ $noautotag = false;
+ if ($stream->test(Twig_Token::NAME_TYPE, 'noautotag')) {
+ $noautotag = true;
+ $stream->next();
+ }
+
$stream->expect(Twig_Token::BLOCK_END_TYPE);
$endtag = 'end'.$this->getTag();
$test = function(Twig_Token $token) use($endtag) { return $token->test($endtag); };
$body = $this->parser->subparse($test, true);
-
$stream->expect(Twig_Token::BLOCK_END_TYPE);
- return new CreatephpNode($body, $modelname, $var, $token->getLine(), $this->getTag());
+ return new CreatephpNode($body, $modelname, $var, !$noautotag, $token->getLine(), $this->getTag());
}
public function getTag()
diff --git a/src/Midgard/CreatePHP/Mapper/DoctrinePhpcrOdmMapper.php b/src/Midgard/CreatePHP/Mapper/DoctrinePhpcrOdmMapper.php
index d58b98d..4355ce8 100644
--- a/src/Midgard/CreatePHP/Mapper/DoctrinePhpcrOdmMapper.php
+++ b/src/Midgard/CreatePHP/Mapper/DoctrinePhpcrOdmMapper.php
@@ -37,12 +37,12 @@ public function prepareObject(TypeInterface $type, $parent = null)
/** @var $meta \Doctrine\ODM\PHPCR\Mapping\ClassMetadata */
$meta = $this->om->getClassMetaData(get_class($object));
- if (!property_exists($object, $meta->parentMapping['fieldName'])) {
+ if (!property_exists($object, $meta->parentMapping)) {
throw new RuntimeException('parentMapping need to be mapped to '
. get_class($object));
}
- $meta->setFieldValue($object, $meta->parentMapping['fieldName'], $parent);
+ $meta->setFieldValue($object, $meta->parentMapping, $parent);
return $object;
}
@@ -123,7 +123,7 @@ private function determineEntityTitle(EntityInterface $entity)
$object = $entity->getObject();
//is there a getTitle method?
- if (method_exists($object, 'getTitle') && $object->getTitle() !== '') {
+ if (method_exists($object, 'getTitle') && $object->getTitle()) {
return $object->getTitle();
} else {
//try to get a property containing title in the rdf description
diff --git a/src/Midgard/CreatePHP/Node.php b/src/Midgard/CreatePHP/Node.php
index 327af92..d67e475 100644
--- a/src/Midgard/CreatePHP/Node.php
+++ b/src/Midgard/CreatePHP/Node.php
@@ -17,7 +17,7 @@
* attributes, parent/children relations and rendering. The latter is split into three
* different functions for maximum flexibility. So you can call render() to output the
* complete node HTML, or you can call render_start() for the opening tag, render_content()
- * for the node's content (or children) and render_end() for the colsing tag.
+ * for the node's content (or children) and render_end() for the closing tag.
*
* @package Midgard.CreatePHP
*/
@@ -245,12 +245,13 @@ public function renderStart($tag_name = false)
$this->_tag_name = $tag_name;
}
+ $attributesToSkip = array();
+
if ( $this->_parent
&& $this->_parent->isRendering())
{
//remove about to work around a VIE bug with nested identical about attributes
- $about_backup = $this->getAttribute('about');
- $this->unsetAttribute('about');
+ $attributesToSkip[] = 'about';
}
$template = explode('__CONTENT__', $this->_template);
@@ -259,14 +260,9 @@ public function renderStart($tag_name = false)
$replace = array
(
"__TAG_NAME__" => $this->_tag_name,
- " __ATTRIBUTES__" => $this->renderAttributes(),
+ " __ATTRIBUTES__" => $this->renderAttributes($attributesToSkip),
);
- if (!empty($about_backup))
- {
- $this->setAttribute('about', $about_backup);
- }
-
$this->_is_rendering = true;
return strtr($template, $replace);
}
@@ -278,11 +274,21 @@ public function renderStart($tag_name = false)
*/
public function render($tag_name = false)
{
- $output = $this->renderStart($tag_name);
+ $output = '';
+ /**
+ * Do not render start and end again if the node is already rendering.
+ */
+ $rendering = $this->isRendering();
+ if (! $rendering) {
+ $output = $this->renderStart($tag_name);
+ }
$output .= $this->renderContent();
- $output .= $this->renderEnd();
+ if (! $rendering) {
+ $output .= $this->renderEnd();
+ }
+
return $output;
}
@@ -291,11 +297,15 @@ public function render($tag_name = false)
*
* @api
*/
- public function renderAttributes()
+ public function renderAttributes(array $attributesToSkip = array())
{
// add additional attributes
$attributes = '';
+ $swappedAttributes = array_flip($attributesToSkip);
foreach ($this->_attributes as $key => $value) {
+ if (isset($swappedAttributes[$key])) {
+ continue;
+ }
$attributes .= ' ' . $key . '="' . $value . '"';
}
if ($attributes === ' ') {
diff --git a/src/Midgard/CreatePHP/NodeInterface.php b/src/Midgard/CreatePHP/NodeInterface.php
index 24c92b8..2854a93 100644
--- a/src/Midgard/CreatePHP/NodeInterface.php
+++ b/src/Midgard/CreatePHP/NodeInterface.php
@@ -104,11 +104,14 @@ public function getAttributes();
public function unsetAttribute($key);
/**
- * Renders everything including wrapper html tag and properties
+ * Renders everything needed.
*
* If you want more control over the generated HTML, call renderStart,
* renderContent and renderEnd separately
*
+ * If called after renderStart but before renderEnd, it will just do
+ * renderContent to not duplicate the wrapper html tag and properties
+ *
* @param string $tag_name
*
* @return string the rendered html
@@ -142,9 +145,11 @@ public function renderEnd();
* Render just the attributes. This is not needed if you use
* renderStart()
*
+ * @param array $attributesToSkip attributes names that will not be printed
+ *
* @return string the rendered attributes
*/
- public function renderAttributes();
+ public function renderAttributes(array $attributesToSkip = array());
/**
* Has to return the same as self::render()
diff --git a/tests/Test/Midgard/CreatePHP/Collection.php b/tests/Test/Midgard/CreatePHP/Collection.php
new file mode 100644
index 0000000..76a3b99
--- /dev/null
+++ b/tests/Test/Midgard/CreatePHP/Collection.php
@@ -0,0 +1,25 @@
+mapper = $this->getMock('Midgard\CreatePHP\RdfMapperInterface');
- $this->factory = new RdfTypeFactory($this->mapper);
+
+ $xmlDriver = new RdfDriverXml(array(__DIR__.'/../../Metadata/rdf-twig'));
+ $this->factory = new RdfTypeFactory($this->mapper, $xmlDriver);
$this->twig = new \Twig_Environment();
$this->twig->setLoader(new \Twig_Loader_Filesystem(__DIR__.'/templates'));
$this->twig->addExtension(new CreatephpExtension($this->factory));
}
- public function testNode()
+ /**
+ * Test the basic Twig templates of CreatePHP (no collections). The
+ * following templates need to render the same html: node.twig,
+ * node_as.twig and functions.twig:
+ *
+ *
+ *
+ *
content text
+ *
content text
+ *
+ *
+ *
+ * @dataProvider templateNameDataProvider
+ */
+ public function testBasicTemplates($templateName)
{
- $this->twig->addGlobal('mymodel', new Model);
-
- $this->mapper->expects($this->any())
- ->method('getPropertyValue')
- ->will($this->returnValue('content text'))
- ;
- $this->mapper->expects($this->any())
- ->method('isEditable')
- ->will($this->returnValue(true))
- ;
- $this->mapper->expects($this->any())
- ->method('createSubject')
- ->will($this->returnValue('/the/subject'))
- ;
-
- $xml = $this->renderXml('node.twig');
-
+ $this->prepareBasicTest();
+ $xml = $this->renderXml($templateName);
$this->assertCompiledCorrectly($xml);
+ }
+ public function templateNameDataProvider()
+ {
+ return array(
+ array('node.twig'),
+ array('node_as.twig'),
+ array('functions.twig')
+ );
}
- public function testNodeAs()
+ public function testCollectionsTemplate()
{
- $this->twig->addGlobal('mymodel', new Model);
+ $collection = new Collection;
+ $this->twig->addGlobal('mycollection', $collection);
+
$this->mapper->expects($this->any())
->method('getPropertyValue')
- ->will($this->returnValue('content text'))
+ ->will($this->returnCallback(array($this, 'getPropertyValueCallback')))
;
$this->mapper->expects($this->any())
->method('isEditable')
@@ -70,22 +91,96 @@ public function testNodeAs()
;
$this->mapper->expects($this->any())
->method('createSubject')
- ->will($this->returnValue('/the/subject'))
+ ->will($this->returnCallback(array($this, 'createSubjectCallback')))
+ ;
+ $this->mapper->expects($this->any())
+ ->method('getChildren')
+ ->will($this->returnValue($collection->getChildren()))
+ ;
+ $this->mapper->expects($this->any())
+ ->method('canonicalName')
+ ->will($this->returnCallback(array($this, 'canonicalNameCallback')))
;
- $xml = $this->renderXml('node_as.twig');
+ $xml = $this->renderXml('collection.twig');
+
+ //assert no duplicate enclosing div is present
+ $this->assertEquals(0, count($xml->div));
+
+ //assert the enclosing div is correct
+ $this->assertEquals('/the/subject/collection', $xml['about']);
+ $this->assertEquals('my-class', $xml['class']);
+ $this->assertEquals('sioc:Forum', $xml['typeof']);
+ $namespaces = $xml->getDocNamespaces(true);
+ $this->assertEquals('http://purl.org/dc/terms/', $namespaces['dcterms']);
+ $this->assertEquals('http://rdfs.org/sioc/ns#', $namespaces['sioc']);
+
+ //assert the collection content is correct
+ $this->assertEquals(1, count($xml->h1));
+ $this->assertEquals('the collection title', $xml->h1);
+ $this->assertEquals('dcterms:title', $xml->h1['property']);
+
+ //assert the listing of children is correct
+ $this->assertEquals(1, count($xml->ul));
+ $this->assertEquals(0, count($xml->ul['about']));
+ $this->assertEquals(2, count($xml->ul->li));
+ $this->assertEquals('dcterms:hasPart', $xml->ul['rel']);
+ $this->assertEquals('dcterms:partOf', $xml->ul['rev']);
+
+ //assert the 1st children is correct
+ $this->assertEquals('sioc:Post', $xml->ul->li['typeof']);
+ $this->assertEquals('/the/subject/model/1', $xml->ul->li['about']);
+ $this->assertEquals('title 1', (string) $xml->ul->li->div[0]);
+ $this->assertEquals('dcterms:title', $xml->ul->li->div[0]['property']);
+ $this->assertEquals('content 1', (string) $xml->ul->li->div[1]);
+ $this->assertEquals('sioc:content', $xml->ul->li->div[1]['property']);
+
+ //assert the 2nd children is correct
+ $this->assertEquals('sioc:Post', $xml->ul->li[1]['typeof']);
+ $this->assertEquals('/the/subject/model/2', $xml->ul->li[1]['about']);
+ $this->assertEquals('title 2', (string) $xml->ul->li[1]->div[0]);
+ $this->assertEquals('dcterms:title', $xml->ul->li[1]->div[0]['property']);
+ $this->assertEquals('content 2', (string) $xml->ul->li[1]->div[1]);
+ $this->assertEquals('sioc:content', $xml->ul->li[1]->div[1]['property']);
+ }
- $this->assertCompiledCorrectly($xml);
+ public function canonicalNameCallback($className) {
+
+ if ($className === 'Test\Midgard\CreatePHP\Collection') {
+ return 'Test\Midgard\CreatePHP\Collection';
+ } else {
+ return 'Test\Midgard\CreatePHP\Model';
+ }
}
- public function testFunctions()
+ public function getPropertyValueCallback($object, PropertyInterface $property)
{
- $this->twig->addGlobal('mymodel', new Model);
+ $name = $property->getIdentifier();
+ if (method_exists($object, 'getObject')) {
+ $object = $object->getObject();
+ }
+ $method = 'get' . ucfirst($name);
+ if (method_exists($object, $method)) {
+ return $object->$method();
+ }
+ throw new \Exception('Invalid call to getPropertyValue');
+ }
+
+ public function createSubjectCallback($object)
+ {
+ if (method_exists($object, 'getObject')) {
+ $object = $object->getObject();
+ }
+ return $object->getSubject();
+ }
+
+ private function prepareBasicTest(){
+ $model = new Model;
+ $this->twig->addGlobal('mymodel', $model);
- $this->twig->addGlobal('mymodel', new Model);
$this->mapper->expects($this->any())
->method('getPropertyValue')
- ->will($this->returnValue('content text'))
+ ->will($this->returnCallback(array($this, 'getPropertyValueCallback')))
;
$this->mapper->expects($this->any())
->method('isEditable')
@@ -95,20 +190,25 @@ public function testFunctions()
->method('createSubject')
->will($this->returnValue('/the/subject'))
;
-
- $xml = $this->renderXml('functions.twig');
-
- $this->assertCompiledCorrectly($xml);
+ $this->mapper->expects($this->any())
+ ->method('canonicalName')
+ ->with(get_class($model))
+ ->will($this->returnValue(get_class($model)))
+ ;
}
private function assertCompiledCorrectly(\SimpleXMLElement $xml)
{
$this->assertEquals(1, count($xml->div));
$this->assertEquals('/the/subject', $xml->div['about']);
- // TODO: how to get to namesapce? $this->assertEquals('http://purl.org/dc/terms/', $xml->div['xmlns:dcterms']);
+ $namespaces = $xml->getDocNamespaces(true);
+ $this->assertEquals('http://purl.org/dc/terms/', $namespaces['dcterms']);
$this->assertEquals(1, count($xml->div->div));
- $this->assertEquals('content text', $xml->div->div);
- $this->assertEquals('dcterms:title', $xml->div->div['property']);
+ $this->assertEquals('dcterms:title', $xml->div->h2['property']);
+ $this->assertEquals('the model title', (string) $xml->div->h2);
+ $this->assertEquals('sioc:content', $xml->div->div['property']);
+ $this->assertEquals('the model content', (string) $xml->div->div);
+
}
/**
@@ -132,4 +232,19 @@ private function dumpCompiledTemplate($template)
var_dump($this->twig->compileSource($source, $template));
die;
}
+
+ /**
+ * Only for debugging, write an xml object into a file
+ *
+ * @param $filename
+ * @param SimpleXMLElement $xml
+ */
+ private function writeXmlToFile($filename, SimpleXMLElement $xml)
+ {
+ $dom = new DOMDocument;
+ $dom->preserveWhiteSpace = FALSE;
+ $dom->loadXML($xml->asXML());
+ $dom->formatOutput = TRUE;
+ $dom->save($filename);
+ }
}
diff --git a/tests/Test/Midgard/CreatePHP/Extension/Twig/RdfTypeFactory.php b/tests/Test/Midgard/CreatePHP/Extension/Twig/RdfTypeFactory.php
deleted file mode 100644
index 1702157..0000000
--- a/tests/Test/Midgard/CreatePHP/Extension/Twig/RdfTypeFactory.php
+++ /dev/null
@@ -1,41 +0,0 @@
-mapper = $mapper;
- }
-
- /**
- * Get the type if this is the expected model class
- */
- public function getTypeByObject($class) {
- if ($class instanceof Model) {
- $type = new Type($this->mapper);
- $type->setVocabulary('dcterms', 'http://purl.org/dc/terms/');
- $prop = new \Midgard\CreatePHP\Entity\Property('title', array());
- $prop->setAttributes(array('property' => 'dcterms:title'));
- $type->title = $prop;
- return $type;
- }
-
- throw new \Exception('No type found for ' . get_class($class));
- }
-
-}
\ No newline at end of file
diff --git a/tests/Test/Midgard/CreatePHP/Extension/Twig/templates/collection.twig b/tests/Test/Midgard/CreatePHP/Extension/Twig/templates/collection.twig
new file mode 100644
index 0000000..2015720
--- /dev/null
+++ b/tests/Test/Midgard/CreatePHP/Extension/Twig/templates/collection.twig
@@ -0,0 +1,19 @@
+{% createphp mycollection as="rdf" noautotag %}
+
+
+
{{ createphp_content( rdf.title ) }}
+
+
+
+
+
+{% endcreatephp %}
\ No newline at end of file
diff --git a/tests/Test/Midgard/CreatePHP/Extension/Twig/templates/functions.twig b/tests/Test/Midgard/CreatePHP/Extension/Twig/templates/functions.twig
index 2d5d8f3..69404fa 100644
--- a/tests/Test/Midgard/CreatePHP/Extension/Twig/templates/functions.twig
+++ b/tests/Test/Midgard/CreatePHP/Extension/Twig/templates/functions.twig
@@ -1,7 +1,8 @@
- {% createphp mymodel %}
+ {% createphp mymodel noautotag %}
-
{{ createphp_content( mymodel_rdf.title ) }}
+
{{ createphp_content( mymodel_rdf.title ) }}
+
{{ createphp_content( mymodel_rdf.content ) }}
{% endcreatephp %}
\ No newline at end of file
diff --git a/tests/Test/Midgard/CreatePHP/Metadata/RdfDriverXmlTest.php b/tests/Test/Midgard/CreatePHP/Metadata/RdfDriverXmlTest.php
index 2724c51..49bf5e1 100644
--- a/tests/Test/Midgard/CreatePHP/Metadata/RdfDriverXmlTest.php
+++ b/tests/Test/Midgard/CreatePHP/Metadata/RdfDriverXmlTest.php
@@ -15,7 +15,7 @@ class RdfDriverXmlTest extends RdfDriverBase
public function setUp()
{
- $this->driver = new RdfDriverXml(array(__DIR__ . DIRECTORY_SEPARATOR . 'rdf'));
+ $this->driver = new RdfDriverXml(array(__DIR__ . DIRECTORY_SEPARATOR . 'rdf-driver'));
}
public function testLoadTypeForClass()
diff --git a/tests/Test/Midgard/CreatePHP/Metadata/rdf/Test.Midgard.CreatePHP.Model.xml b/tests/Test/Midgard/CreatePHP/Metadata/rdf-driver/Test.Midgard.CreatePHP.Model.xml
similarity index 100%
rename from tests/Test/Midgard/CreatePHP/Metadata/rdf/Test.Midgard.CreatePHP.Model.xml
rename to tests/Test/Midgard/CreatePHP/Metadata/rdf-driver/Test.Midgard.CreatePHP.Model.xml
diff --git a/tests/Test/Midgard/CreatePHP/Metadata/rdf-twig/Test.Midgard.CreatePHP.Collection.xml b/tests/Test/Midgard/CreatePHP/Metadata/rdf-twig/Test.Midgard.CreatePHP.Collection.xml
new file mode 100644
index 0000000..0d7b021
--- /dev/null
+++ b/tests/Test/Midgard/CreatePHP/Metadata/rdf-twig/Test.Midgard.CreatePHP.Collection.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/tests/Test/Midgard/CreatePHP/Metadata/rdf-twig/Test.Midgard.CreatePHP.Model.xml b/tests/Test/Midgard/CreatePHP/Metadata/rdf-twig/Test.Midgard.CreatePHP.Model.xml
new file mode 100644
index 0000000..0d9026c
--- /dev/null
+++ b/tests/Test/Midgard/CreatePHP/Metadata/rdf-twig/Test.Midgard.CreatePHP.Model.xml
@@ -0,0 +1,11 @@
+
+ dcterms:partOf
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Test/Midgard/CreatePHP/Model.php b/tests/Test/Midgard/CreatePHP/Model.php
index d1b582f..f22253c 100644
--- a/tests/Test/Midgard/CreatePHP/Model.php
+++ b/tests/Test/Midgard/CreatePHP/Model.php
@@ -4,12 +4,28 @@
class Model
{
+ private $title;
+ private $content;
+ private $subject;
+
+ public function __construct($title = 'the model title',
+ $content = 'the model content',
+ $subject = '/the/subject/model')
+ {
+ $this->title = $title;
+ $this->content = $content;
+ $this->subject = $subject;
+ }
public function getTitle()
{
- return 'the title';
+ return $this->title;
}
public function getContent()
{
- return 'the content';
+ return $this->content;
+ }
+ public function getSubject()
+ {
+ return $this->subject;
}
}
\ No newline at end of file