diff --git a/Module.php b/Module.php index d74b6b7..e372586 100644 --- a/Module.php +++ b/Module.php @@ -38,7 +38,8 @@ public function getServiceConfig() $service = new \EdpDiscuss\Service\Discuss; $service->setThreadMapper($sm->get('edpdiscuss_thread_mapper')) ->setMessageMapper($sm->get('edpdiscuss_message_mapper')) - ->setTagMapper($sm->get('edpdiscuss_tag_mapper')); + ->setTagMapper($sm->get('edpdiscuss_tag_mapper')) + ->setVisitMapper($sm->get('edpdiscuss_visit_mapper')); return $service; }, 'edpdiscuss_thread_mapper' => function($sm) { @@ -66,6 +67,17 @@ public function getServiceConfig() $mapper->setHydrator(new \Zend\Stdlib\Hydrator\ClassMethods); return $mapper; }, + 'edpdiscuss_visit_mapper' => function($sm) { + $mapper = new \EdpDiscuss\Model\Visit\VisitMapper; + $visitModelClass = Module::getOption('visit_model_class'); + $mapper->setEntityPrototype(new $visitModelClass); + $mapper->setHydrator(new \Zend\StdLib\Hydrator\ClassMethods); + return $mapper; + }, + 'edpdiscuss_thread' => function ($sm) { + $thread = new \EdpDiscuss\Model\Thread\Thread; + return $thread; + }, 'edpdiscuss_message' => function ($sm) { $message = new \EdpDiscuss\Model\Message\Message; return $message; @@ -74,6 +86,12 @@ public function getServiceConfig() $form = new \EdpDiscuss\Form\PostForm; return $form; }, + 'edpdiscuss_visit' => function ($sm) { + $visit = new \EdpDiscuss\Model\Visit\Visit; + $visit->setIpAddress($_SERVER['REMOTE_ADDR']) + ->setVisitTime(new \DateTime); + return $visit; + } ), 'initializers' => array( function($instance, $sm){ @@ -117,4 +135,14 @@ public static function getOption($option) } return static::$options[$option]; } + + public function getViewHelperConfig() + { + return array( + 'invokables' => array( + 'RenderForm' => 'EdpDiscuss\View\Helper\RenderForm' + ) + ); + + } } diff --git a/README.md b/README.md index 1bc8e42..deb701c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ Requirements ------------ * [Zend Framework 2](https://github.com/zendframework/zf2) (latest master) -* [ZfcBase](https://github.com/ZF-Commons/ZfcBase) (latest master). +* [ZfcBase](https://github.com/ZF-Commons/ZfcBase) (latest master) +* [BaconStringUtils] (https://github.com/Bacon/BaconStringUtils) Installation ------------ @@ -17,16 +18,44 @@ Installation 1. Install the [ZfcBase](https://github.com/ZF-Commons/ZfcBase) ZF2 module by cloning it into `./vendor/`. -2. Clone this project into your `./vendor/` directory. +2. Install the [BaconStringUtils] (https://github.com/Bacon/BaconStringUtils) ZF2 module + by cloning it into `./vendor/`. +3. Clone this project into your `./vendor/` directory. Post Installation ----------------- -Import the SQL schema located in `./vendor/EdpDiscuss/data/schema.sql`. +1. Enabling the modules in your `application.config.php` file. + + ```php + array( + // ... + 'ZfcBase', + 'BaconStringUtils', + 'EdpDiscuss', + ), + // ... + ); + ``` +2. Import the SQL schema located in `./vendor/EdpDiscuss/data/schema.sql`. Introduction ------------ EdpDiscuss is a module for Zend Framework 2. + +Options +------- + +The EdpDiscuss module has various options to allow you to quickly customize the basic functionality. + +The following options are available: + +- **thread_model_class** - Name of Thread entity class to use. +- **message_model_class** - Name of Message entity class to use. +- **tag_model_class** - Name of Tag entity class to use. +- **visit_model_class** - Name of Visit Entity class to use. \ No newline at end of file diff --git a/config/module.config.php b/config/module.config.php index bdc6185..5784caf 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -4,6 +4,7 @@ 'thread_model_class' => 'EdpDiscuss\Model\Thread\Thread', 'message_model_class' => 'EdpDiscuss\Model\Message\Message', 'tag_model_class' => 'EdpDiscuss\Model\Tag\Tag', + 'visit_model_class' => 'EdpDiscuss\Model\Visit\Visit' ), 'service_manager' => array( 'aliases' => array( diff --git a/data/schema.sql b/data/schema.sql index 6738b4d..4b6a040 100644 --- a/data/schema.sql +++ b/data/schema.sql @@ -1,20 +1,20 @@ CREATE TABLE discuss_thread ( - thread_id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, + thread_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL, subject VARCHAR(1000) NOT NULL, slug VARCHAR(255) NOT NULL ) ENGINE=InnoDB; CREATE TABLE discuss_message ( - message_id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, + message_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL, post_time DATETIME NOT NULL, - author_user_id INTEGER DEFAULT NULL, + author_user_id INT UNSIGNED DEFAULT NULL, author_email VARCHAR(255) DEFAULT NULL UNIQUE, author_name VARCHAR(50) DEFAULT NULL, - thread_id INTEGER NOT NULL, - parent_message_id INTEGER DEFAULT NULL, - subject VARCHAR(100) DEFAULT NOT NULL, + thread_id INT UNSIGNED NOT NULL, + parent_message_id INT UNSIGNED DEFAULT NULL, + subject VARCHAR(100) NOT NULL, message TEXT NOT NULL, FOREIGN KEY (author_user_id) REFERENCES user (user_id), FOREIGN KEY (thread_id) REFERENCES discuss_thread (thread_id) ON DELETE CASCADE, @@ -23,15 +23,24 @@ CREATE TABLE discuss_message CREATE TABLE discuss_tag ( - tag_id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, + tag_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, slug VARCHAR(255) NOT NULL ) ENGINE=InnoDB; CREATE TABLE discuss_thread_tag ( - thread_id INTEGER NOT NULL, - tag_id INTEGER DEFAULT NULL, + thread_id INT UNSIGNED NOT NULL, + tag_id INT UNSIGNED DEFAULT NULL, FOREIGN KEY (thread_id) REFERENCES discuss_thread (thread_id), FOREIGN KEY (tag_id) REFERENCES discuss_tag (tag_id) ) ENGINE=InnoDB; + +CREATE TABLE discuss_visit +( + ip_address VARCHAR(45) NOT NULL, + thread_id INT UNSIGNED NOT NULL, + visit_time DATETIME NOT NULL, + PRIMARY KEY(ip_address, thread_id), + FOREIGN KEY (thread_id) REFERENCES discuss_thread(thread_id) +) ENGINE=InnoDB; \ No newline at end of file diff --git a/src/EdpDiscuss/Form/PostForm.php b/src/EdpDiscuss/Form/PostForm.php index 56fb5b0..3653066 100644 --- a/src/EdpDiscuss/Form/PostForm.php +++ b/src/EdpDiscuss/Form/PostForm.php @@ -27,7 +27,9 @@ public function __construct() ), 'attributes' => array( 'type' => 'text', + 'class' => 'form-control', ), + )); $this->add(array( @@ -36,8 +38,11 @@ public function __construct() 'label' => 'Message', ), 'attributes' => array( - 'type' => 'text', + 'type' => 'textarea', + 'class' => 'form-control', + 'rows' => '6', ), + )); // Submit button. diff --git a/src/EdpDiscuss/Model/Message/MessageHydrator.php b/src/EdpDiscuss/Model/Message/MessageHydrator.php index 0883498..748c79c 100644 --- a/src/EdpDiscuss/Model/Message/MessageHydrator.php +++ b/src/EdpDiscuss/Model/Message/MessageHydrator.php @@ -30,15 +30,7 @@ public function extract($object) $thread = $object->getThread(); $data['thread_id'] = (int)$thread->getThreadId(); unset($data['thread']); - - $data['post_time'] = $data['post_time']->format('Y-m-d H:i:s'); - - //die(var_dump($data)); - - // Example of how to map fields. - //$data = $this->mapField('id', 'user_id', $data); - return $data; } diff --git a/src/EdpDiscuss/Model/Tag/Tag.php b/src/EdpDiscuss/Model/Tag/Tag.php index b66c48b..7a72366 100644 --- a/src/EdpDiscuss/Model/Tag/Tag.php +++ b/src/EdpDiscuss/Model/Tag/Tag.php @@ -3,6 +3,7 @@ namespace EdpDiscuss\Model\Tag; use BaconStringUtils\Slugifier; +use DateTime; class Tag implements TagInterface { @@ -15,6 +16,11 @@ class Tag implements TagInterface * @var string */ protected $name; + + /** + * @var string + */ + protected $description; /** * @var string @@ -26,6 +32,21 @@ class Tag implements TagInterface */ protected $slugifier; + /** + * @var integer + */ + protected $threadCount; + + /** + * @var integer + */ + protected $messageCount; + + /** + * @var Date + */ + protected $lastPost; + /** * Get tagId. * @@ -69,6 +90,27 @@ public function setName($name) return $this; } + /** + * Get description. + * + * @return description + */ + public function getDescription() + { + return $this->description; + } + + /** + * Set description. + * + * @param $description the value to be set + */ + public function setDescription($description) + { + $this->description = $description; + return $this; + } + /** * Get slug. * @@ -90,6 +132,11 @@ public function setSlug($slug) return $this; } + /** + * Get Slugifier. + * + * @return Slugifier + */ public function getSlugifier() { if ($this->slugifier === null) { @@ -98,9 +145,80 @@ public function getSlugifier() return $this->slugifier; } + /** + * Set Slugifier. + * + * @param Slugifier + */ public function setSlugifier($slugifier) { $this->slugifier = $slugifier; return $this; } + + /** + * Set thread count. + * @param integer $threadCount + */ + public function setThreadCount($threadCount) + { + $this->threadCount = $threadCount; + return $this; + } + + /** + * Get thread count. + * + * @return integer + */ + public function getThreadCount() + { + return $this->threadCount; + } + + /** + * Set Message Count. + * + * @param integer $messageCount + */ + public function setMessageCount($messageCount) + { + $this->messageCount = $messageCount; + return $this; + } + + /** + * Get Message Count. + * + * @return integer + */ + public function getMessageCount() + { + return $this->messageCount; + } + + /** + * Set Last Post + * + * @param Date $lastPost + */ + public function setLastPost($lastPost) + { + if ($lastPost instanceof DateTime) { + $this->lastPost = $lastPost; + } else { + $this->lastPost = new DateTime($lastPost); + } + return $this; + } + + /** + * Get Last Post. + * + * @return Date + */ + public function getLastPost() + { + return $this->lastPost; + } } diff --git a/src/EdpDiscuss/Model/Tag/TagInterface.php b/src/EdpDiscuss/Model/Tag/TagInterface.php index e62fbed..e61b3be 100644 --- a/src/EdpDiscuss/Model/Tag/TagInterface.php +++ b/src/EdpDiscuss/Model/Tag/TagInterface.php @@ -31,6 +31,20 @@ public function getName(); * @param $name the value to be set */ public function setName($name); + + /** + * Get description. + * + * @return description + */ + public function getDescription(); + + /** + * Set description. + * + * @param $description the value to be set + */ + public function setDescription($description); /** * Get slug. diff --git a/src/EdpDiscuss/Model/Tag/TagMapper.php b/src/EdpDiscuss/Model/Tag/TagMapper.php index f22b96b..3b6bbbe 100644 --- a/src/EdpDiscuss/Model/Tag/TagMapper.php +++ b/src/EdpDiscuss/Model/Tag/TagMapper.php @@ -5,6 +5,8 @@ use ZfcBase\Mapper\AbstractDbMapper; use EdpDiscuss\Module as EdpDiscuss; use EdpDiscuss\Service\DbAdapterAwareInterface; +use Zend\Db\Sql\Sql; +use Zend\Db\Sql\Expression; class TagMapper extends AbstractDbMapper implements TagMapperInterface, DbAdapterAwareInterface { @@ -23,4 +25,45 @@ public function getTagById($tagId) return $this->select($select)->current(); } + + /** + * getTags + * + * @return array of TagInterface's + */ + public function getTags() + { + $select = $this->getSelect(); + $select->join(array('tt' => 'discuss_thread_tag'), + 'tt.tag_id = discuss_tag.tag_id', + array(), + 'left') + ->join(array('t' => 'discuss_thread'), + 't.thread_id = tt.thread_id', + array('thread_count' => new Expression('COUNT(DISTINCT t.thread_id)')), + 'left') + ->join(array('m' => 'discuss_message'), + 'm.thread_id = t.thread_id', + array('last_post' => new Expression('MAX(m.post_time)'), + 'message_count' => new Expression('COUNT(m.message_id)')), + 'left') + ->group(array('discuss_tag.name', 'discuss_tag.slug', 'discuss_tag.description')); + return $this->select($select); + } + + /** + * Add Thread. + * + * @param integer $tag_id + * @param integer $thread_id + */ + public function addThread($tag_id, $thread_id) + { + $sql = new Sql($this->getDbAdapter()); + $insert = $sql->insert(); + $insert->into('discuss_thread_tag'); + $insert->values(array('tag_id' => $tag_id, 'thread_id' => $thread_id)); + $sql->prepareStatementForSqlObject($insert) + ->execute(); + } } diff --git a/src/EdpDiscuss/Model/Tag/TagMapperInterface.php b/src/EdpDiscuss/Model/Tag/TagMapperInterface.php index 0a3b91a..326bcf6 100644 --- a/src/EdpDiscuss/Model/Tag/TagMapperInterface.php +++ b/src/EdpDiscuss/Model/Tag/TagMapperInterface.php @@ -11,4 +11,11 @@ interface TagMapperInterface * @return TagInterface */ public function getTagById($tagId); + + /** + * getTags + * + * @return array of TagInterface's + */ + public function getTags(); } diff --git a/src/EdpDiscuss/Model/Thread/Thread.php b/src/EdpDiscuss/Model/Thread/Thread.php index 5559a78..7578bf6 100644 --- a/src/EdpDiscuss/Model/Thread/Thread.php +++ b/src/EdpDiscuss/Model/Thread/Thread.php @@ -2,9 +2,10 @@ namespace EdpDiscuss\Model\Thread; -use ZfcBase\Model\ModelAbstract, - BaconStringUtils\Slugifier, - EdpDiscuss\Model\Message\MessageInterface; +use ZfcBase\Model\ModelAbstract; +use BaconStringUtils\Slugifier; +use EdpDiscuss\Model\Message\MessageInterface; +use DateTime; class Thread implements ThreadInterface { @@ -38,6 +39,21 @@ class Thread implements ThreadInterface */ protected $slugifier; + /** + * @var integer + */ + protected $messageCount; + + /** + * @var integer + */ + protected $visitCount; + + /** + * @var Date + */ + protected $lastPost; + /** * Get threadId. * @@ -157,4 +173,72 @@ public function setSlugifier($slugifier) $this->slugifier = $slugifier; return $this; } + + /** + * Set Message Count. + * + * @param integer $messageCount + */ + public function setMessageCount($messageCount) + { + $this->messageCount = $messageCount; + return $this; + } + + /** + * Get Message Count. + * + * @return integer + */ + public function getMessageCount() + { + return $this->messageCount; + } + + /** + * Set View Count + * + * Enter description here ... + * @param unknown_type $viewCount + */ + public function setVisitCount($viewCount) + { + $this->viewCount = $viewCount; + return $this; + } + + /** + * Get View Count + * + * @return integer + */ + public function getVisitCount() + { + return $this->viewCount; + } + + /** + * Set Last Post + * + * @param DateTime $lastPost + */ + public function setLastPost($lastPost) + { + if ($lastPost instanceof DateTime) { + $this->lastPost = $lastPost; + } else { + $this->lastPost = new DateTime($lastPost); + } + return $this; + } + + /** + * Get Last Post. + * + * @return Date + */ + public function getLastPost() + { + return $this->lastPost; + } } diff --git a/src/EdpDiscuss/Model/Thread/ThreadHydrator.php b/src/EdpDiscuss/Model/Thread/ThreadHydrator.php new file mode 100644 index 0000000..2c895c3 --- /dev/null +++ b/src/EdpDiscuss/Model/Thread/ThreadHydrator.php @@ -0,0 +1,47 @@ +from('discuss_thread') - ->join('discuss_thread_tag', 'discuss_thread_tag.thread_id = discuss_thread.thread_id') - ->where(array('tag_id = ?' => $tagId)); - $rowset = $this->select($select); - } else { - $rowset = $this->select(); - } - - return $rowset; + $select = $this->getSelect(); + $select->join(array('tt' => 'discuss_thread_tag'), + 'tt.thread_id = discuss_thread.thread_id', + array()) + ->join(array('m' => 'discuss_message'), + 'm.thread_id = discuss_thread.thread_id', + array( + 'message_count' => new Expression('COUNT(DISTINCT m.message_id)'), + 'last_post' => new Expression('MAX(m.post_time)') + ), + 'left') + ->join(array('v' => 'discuss_visit'), + 'v.thread_id = discuss_thread.thread_id', + array( + 'visit_count' => new Expression('COUNT(DISTINCT v.ip_address)') + ), + 'left') + ->where(array('tag_id = ?' => $tagId)) + ->group(array('discuss_thread.subject', 'discuss_thread.slug')); + //die($select->getSqlString()); + return $this->select($select); } /** - * persist + * persist - Persists a thread to the database. * * @param ThreadInterface $thread * @return ThreadInterface */ public function persist(ThreadInterface $thread) { - $data = new ArrayObject($thread->toArray()); if ($thread->getThreadId() > 0) { - $this->getTableGateway()->update((array) $data, array($this->threadIDField => $thread->getThreadId())); + $this->update($thread, null, null, new ThreadHydrator); } else { - $this->getTableGateway()->insert((array) $data); - $threadId = $this->getTableGateway()->getAdapter()->getDriver()->getConnection()->getLastGeneratedId(); - $thread->setThreadId($threadId); + $this->insert($thread, null, new ThreadHydrator); } - + return $thread; } + + /** + * insert - Inserts a new thread into the database, using the specified hydrator. + * + * @param ThreadInterface $entity + * @param String $tableName + * @param HydratorInterface $hydrator + * @return unknown + */ + protected function insert($entity, $tableName = null, HydratorInterface $hydrator = null) + { + //die(var_dump($entity)); + $result = parent::insert($entity, $tableName, $hydrator); + $entity->setThreadId($result->getGeneratedValue()); + return $result; + } + + /** + * update - Updates an existing thread in the database. + * @param ThreadInterface $entity + * @param String $where + * @param String $tableName + * @param HydratorInterface $hydrator + */ + protected function update($entity, $where = null, $tableName = null, HydratorInterface $hydrator = null) + { + if (!$where) { + $where = 'thread_id = ' . $entity->getThreadId(); + } + return parent::update($entity, $where, $tableName, $hydrator); + } } diff --git a/src/EdpDiscuss/Model/Visit/Visit.php b/src/EdpDiscuss/Model/Visit/Visit.php new file mode 100644 index 0000000..db55755 --- /dev/null +++ b/src/EdpDiscuss/Model/Visit/Visit.php @@ -0,0 +1,87 @@ +ipAddress = $ipAddress; + return $this; + } + + /** + * getIpAddress - Returns the IP address. + */ + public function getIpAddress() + { + return $this->ipAddress; + } + + /** + * setVisitTime - Sets the visit time. + * + * @param unknown_type $visitTime + * @return \EdpDiscuss\Model\Visit\Visit + */ + public function setVisitTime($visitTime) + { + if ($visitTime instanceof \DateTime) { + $this->visitTime = $visitTime; + } else { + $this->visitTime = new \DateTime($visitTime); + } + return $this; + } + + /** + * getVisitTime - returns the visit time. + */ + public function getVisitTime() + { + return $this->visitTime; + } + + /** + * setThread - Sets the thread. + * + * @param ThreadInterface $thread + * @return \EdpDiscuss\Model\Visit\Visit + */ + public function setThread(ThreadInterface $thread) + { + $this->thread = $thread; + return $this; + } + + /** + * getThread - returns the thread. + */ + public function getThread() + { + return $this->thread; + } +} diff --git a/src/EdpDiscuss/Model/Visit/VisitHydrator.php b/src/EdpDiscuss/Model/Visit/VisitHydrator.php new file mode 100644 index 0000000..55830f3 --- /dev/null +++ b/src/EdpDiscuss/Model/Visit/VisitHydrator.php @@ -0,0 +1,44 @@ +getThread(); + $data['thread_id'] = (int)$thread->getThreadId(); + unset($data['thread']); + $data['visit_time'] = $data['visit_time']->format('Y-m-d H:i:s'); + return $data; + } + + /** + * hydrate + * + * @param array $data + * @param unknown_type $object + * @throws Exception\InvalidArgumentException + */ + public function hydrate(array $data, $object) + { + if (!$object instanceof VisitInterface) { + throw new Exception\InvalidArgumentException('$object must be an instance of EdpDiscuss\Model\Visit\VisitInterface'); + } + + return parent::hydrate($data, $object); + } +} \ No newline at end of file diff --git a/src/EdpDiscuss/Model/Visit/VisitInterface.php b/src/EdpDiscuss/Model/Visit/VisitInterface.php new file mode 100644 index 0000000..5ad87a5 --- /dev/null +++ b/src/EdpDiscuss/Model/Visit/VisitInterface.php @@ -0,0 +1,44 @@ +getSelect() + ->where(array( + 'ip_address' => $visit->getIpAddress(), + 'thread_id' => $visit->getThread()->getThreadId() + )); + $result = $this->select($select)->current(); + if (!$result) { + parent::insert($visit, null, new VisitHydrator); + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/src/EdpDiscuss/Model/Visit/VisitMapperInterface.php b/src/EdpDiscuss/Model/Visit/VisitMapperInterface.php new file mode 100644 index 0000000..d0e91ed --- /dev/null +++ b/src/EdpDiscuss/Model/Visit/VisitMapperInterface.php @@ -0,0 +1,7 @@ +messageMapper->persist($message); - - $thread->setOriginalMessage($message); + $thread->setSubject($message->getSubject()); $thread = $this->threadMapper->persist($thread); - - $this->events()->trigger(__FUNCTION__, $this, array('thread' => $thread)); - + $message->setPostTime(new \DateTime); + $message = $this->messageMapper->persist($message); + //$this->events()->trigger(__FUNCTION__, $this, array('thread' => $thread)); return $thread; } @@ -114,29 +115,12 @@ public function updateThread(ThreadInterface $thread) /** * createMessage * - * @param array $data + * @param MessageInterface $message * @return MessageInterface */ - public function createMessage(array $data, $thread) + public function createMessage(MessageInterface $message) { - // Create new message object. - $message = $this->getServiceManager()->get('edpdiscuss_message'); - $message->setThread($thread); - - // Create new form and hydrator objects. - $form = $this->getServiceManager()->get('edpdiscuss_form'); - $formHydrator = $this->getServiceManager()->get('edpdiscuss_post_form_hydrator'); - - // validate data against form - $form->setHydrator($formHydrator); - $form->bind($message); - $form->setData($data); - if (!$form->isValid()) - { - return false; - } - - // Valid, so persist message. + // Set post time and persist message. $message->setPostTime(new \DateTime); $message = $this->messageMapper->persist($message); // $this->events()->trigger(__FUNCTION__, $this, array('message' => $message)); @@ -165,6 +149,16 @@ public function getTagById($tagId) { return $this->tagMapper->getTagById($tagId); } + + /** + * getTags + * + * @return array + */ + public function getTags() + { + return $this->tagMapper->getTags(); + } /** * getThreadById @@ -252,4 +246,53 @@ public function setTagMapper(TagMapperInterface $tagMapper) $this->tagMapper = $tagMapper; return $this; } + + /** + * Set Visit Mapper + * + * Enter description here ... + * @param VisitMapperInterface $visitMapper + */ + public function setVisitMapper(VisitMapperInterface $visitMapper) + { + $this->visitMapper = $visitMapper; + return $this; + } + + /** + * Get Vist Mapper. + * + * Enter description here ... + */ + public function getVisitMapper() + { + return $this->visitMapper; + } + + /** + * Associate tag and thread. + * + * @param TagInterface $tag + * @param ThreadInterface $thread + * @return \EdpDiscuss\Service\Discuss + */ + public function associateTagAndThread(TagInterface $tag, ThreadInterface $thread) + { + $this->getTagMapper()->addThread( + $tag->getTagId(), + $thread->getThreadId() + ); + return $this; + } + + /** + * storeVisitIfUnique - records the visit if it is unuiqe. + * @param ThreadInterface $thread + * @return \EdpDiscuss\Service\Discuss + */ + public function storeVisitIfUnique(VisitInterface $visit) + { + $this->getVisitMapper()->storeVisitIfUnique($visit); + return $this; + } } diff --git a/src/EdpDiscuss/View/Helper/RenderForm.php b/src/EdpDiscuss/View/Helper/RenderForm.php new file mode 100644 index 0000000..01e35a7 --- /dev/null +++ b/src/EdpDiscuss/View/Helper/RenderForm.php @@ -0,0 +1,67 @@ +prepare(); + + // Render the output. + $form->setAttribute('class', 'form-horizontal'); + $output = $this->view->form()->openTag($form) . PHP_EOL; + $elements = $form->getElements(); + foreach($elements as $element) + { + $hidden = ($element->getAttribute('type') == 'hidden'); + + $offset = ""; + if ($element->getAttribute('type') == 'submit') + { + $offset ="col-sm-offset-2 "; + } + + if (!$hidden) + { + $messages = $element->getMessages(); + if (empty($messages)) { + $output .= '
' . PHP_EOL; + } else { + $output .= '
'; + } + } + + // Render label if present. + $label = $element->getLabel(); + if (isset($label) && '' !== $label) + { + $element->setLabelAttributes(array('class' => 'col-sm-2 control-label')); + $output .= $this->view->formLabel($element) . PHP_EOL; + } + + // Render the actual element (and any errors) + if (!$hidden) + { + $output .= '
' . PHP_EOL; + } + $output .= $this->view->formElement($element) . PHP_EOL; + $output .= $this->view->formElementErrors($element) . PHP_EOL; + if (!$hidden) + { + $output .= '
' . PHP_EOL; + } + + if (!$hidden) + { + $output .= '
' . PHP_EOL; + } + } + $output .= $this->view->form()->closeTag($form) . PHP_EOL; + + // Return the output. + return $output; + } +} \ No newline at end of file