* @license PHP License * @package WB * @subpackage db */ WBClass::load('WBDatasource_XReference'); /** * Comment everything * * Manage storage of comments for anything related to other tables. Hence, this allows * to comment blog entries as well as users or uploaded files * * @version 0.4.0 * @package WB * @subpackage db */ class WBDatasource_Comment extends WBDatasource_XReference { /** * static constructor * * Load configuration into static property and merge it with * default values. */ static public function staticConstruct() { $conf = array( 'default' => array( 'approvemode' => 'owner', 'creategroup' => '', 'approvegroup' => 'commentadmin', 'deletegroup' => 'commentadmin' ), 'namespaces' => array() ); parent::staticConstructLoader($conf, 'comment'); } /** * user id of origin entry * @var string */ protected $xuid = 0; /** * whether current blog entry is market as approves * @var bool */ protected $approved = false; /** * Tell whether to trigger events * @var bool */ private $triggerEvent = true; /** * Show form element * @var bool */ private $showForm = true; /** * List of filter * @var array */ private $filter = null; /** * Switch usage of event trigger * * @param bool $switch true for on (default) */ public function useEventTrigger($switch = true) { $this->triggerEvent = $switch; } /** * Show form element to add comment * * @param bool $switch */ public function useForm($switch = true) { $this->showForm = $switch; } /** * get list of unapproved comments related to user * * Load list of comments that are not approved yet. Comments * must be related to current user * * @param int $limit * @return array */ public function getUnapproved($limit = null) { $options = array(); if ($limit) { $options['limit'] = $limit; } $clause = array(); $clause[] = array( 'field' => 'x' . $this->uPrimary, 'value' => $this->uid ); $clause[] = array( 'field' => 'approved', 'value' => 0 ); return $this->table->get('comment', null, null, $clause, $options); } /** * Load By Id * * @param string $id * @return array */ public function getById($id) { $data = $this->load($id); return $data; } /** * get comments of user * * Load list of comments done by a specified user * * @param int $limit * @return array */ public function getUserComments($limit) { $options = array(); if ($limit) { $options['limit'] = $limit; } $clause = array(); $clause[] = array( 'field' => $this->uPrimary, 'value' => $this->uid ); $clause[] = array( 'field' => 'approved', 'value' => 1 ); return $this->table->get('comment', null, null, $clause, $options); } /** * Latest Record * * Get latest approved comment * * @return array */ public function getLatest($approved = true) { $this->initFilter(); $clause = $this->getFilteredClause(); // show unapproved in case current user is origin user if ($approved) { $clause[] = array( 'field' => 'approved', 'value' => 1 ); } $options = array(); $options['limit'] = 1; $options['order'] = array(); $options['order'][] = array( 'field' => 'created', 'asc' => 0 ); $last = $this->table->get('comment', null, null, $clause, $options); if (empty($last)) { return array(); } return $last[0]; } /** * browse comments * * Use pager to browse comments of something. Return list of comments and * fill $pagerInfo array. * Usually only approved comments will appear in list. Still origin owner * may see unapproved comments, as well. * * @param array $pagerInfo * @param int $goto page number * @param int $limit comments per page * @return array */ public function browse(&$pagerInfo, $goto = 0, $limit = null) { $options = array(); if ($limit) { $options['limit'] = $limit; } $this->initFilter(); $clause = $this->getFilteredClause(); // show unapproved in case current user is origin user if ($this->xuid != $this->uid) { $clause[] = array( 'field' => 'approved', 'value' => 1 ); } $pid = __CLASS__ . $clause[0]['value'] . $clause[1]['value']; $pager = $this->table->getPager($pid, 'comment', null, $clause, $options); $pagerInfo = $pager->browse($goto); // enrich pager information $pagerInfo['namespace'] = $clause[0]['value']; $pagerInfo['xid'] = $clause[1]['value']; $pagerInfo['xuid'] = $this->xuid; $pagerInfo['showform'] = intval($this->showForm); $pagerInfo['createcomment'] = 0; // allow even not loged in users to add comments if ('*' == self::$conf['namespaces'][$pagerInfo['namespace']]['creategroup']) { $pagerInfo['createcomment'] = 1; } else if ($this->uid) { $pagerInfo['createcomment'] = 1; if ($this->uid != $this->xuid && !empty(self::$conf['namespaces'][$pagerInfo['namespace']]['creategroup']) && !in_array(self::$conf['namespaces'][$pagerInfo['namespace']]['creategroup'], $this->uGroups)) { $pagerInfo['createcomment'] = 0; } } if (!$this->showForm) { $pagerInfo['createcomment'] = 0; } $pagerInfo['deletecomment'] = 0; if ($this->uid) { if ($this->uid == $this->xuid) { $pagerInfo['deletecomment'] = 1; } else if (!empty(self::$conf['namespaces'][$pagerInfo['namespace']]['deletegroup']) && in_array(self::$conf['namespaces'][$pagerInfo['namespace']]['deletegroup'], $this->uGroups)) { $pagerInfo['deletecomment'] = 1; } } $pagerInfo['approvecomment'] = 0; if ($this->uid) { if ($this->uid == $this->xuid) { $pagerInfo['approvecomment'] = 1; } else if (!empty(self::$conf['namespaces'][$pagerInfo['namespace']]['approvegroup']) && in_array(self::$conf['namespaces'][$pagerInfo['namespace']]['approvegroup'], $this->uGroups)) { $pagerInfo['approvecomment'] = 1; } } return $pager->get(); } /** * add new comment * * Save new comment * * @param array|string $comment * @param bool $approve * @return string id */ public function add($comment, $approve = false) { $ns = $this->getNamespace(); $uid = $this->uid; if (empty($uid)) { $uid = self::$conf['namespaces'][$ns]['defaultuser']; } if (!is_array($comment)) { $comment = array('body' => $comment); } $comment['body'] = trim($comment['body']); if (empty($comment['body'])) { return ''; } $data = $this->getCustomCommentData($comment); $data['commentbody'] = $comment['body']; $data[$this->uPrimary] = $uid; $data['x' . $this->uPrimary] = $this->xuid; $data['namespace'] = $ns; $data['xid'] = $this->clause[1]['value']; $this->approved = false; // check whether current user may add a comment if ('*' != self::$conf['namespaces'][$ns]['creategroup']) { if (empty($this->uid)) { return true; } if (!empty(self::$conf['namespaces'][$ns]['creategroup']) && !in_array(self::$conf['namespaces'][$ns]['creategroup'], $this->uGroups)) { return true; } } // approve comment automatically switch (self::$conf['namespaces'][$ns]['approvemode']) { case 'auto'; $approve = true; break; case 'owner': if ($this->uid == $this->xuid) { $approve = true; } break; case 'group': if (in_array(self::$conf['namespaces'][$ns]['approvegroup'], $this->uGroups)) { $approve = true; } break; } $data['approved'] = intval($approve); $id = $this->table->save('comment', '__new', $data); $data['id'] = $id; if ($this->triggerEvent) { WBClass::load('WBEvent'); WBEvent::trigger('comment:added:' . $ns, 'Added comment for {NAMESPACE}:{XID}', $data); } if ($approve) { $this->saveApprove($id, $data); } return $id; } /** * approve comment * * Approve comment. Actually only the owner of the origin entry is allowed to * approve a comment. * * @param string $id * @return WBDatasource_Comment */ public function approve($id) { $data = $this->load($id); // skip already approved records if ($data['approved']) { return $this; } // check whether current user is allowed to approve this comment switch (self::$conf['namespaces'][$data['namespace']]['approvemode']) { case 'owner': if ($data['x' . $this->uPrimary] != $this->uid) { return $this; } break; case 'group': if (!in_array(self::$conf['namespaces'][$data['namespace']]['approvegroup'], $this->uGroups)) { return $this; } break; } $this->saveApprove($id, $data); return $this; } /** * is comment approved? * * Tell whether just added blog entry is approved * * @return bool */ public function isApproved() { return $this->approved; } /** * delete comment * * Remove comment by id. It is only allowed to delete either comments owned by the * current user or when the current user owns the origin entry. Otherwise, it is * just not possible to delete the comment. * * @param string $id * @return WBDatasource_Comment */ public function delete($id) { WBClass::load('WBException_Argument'); $data = $this->load($id); // check whether current user may delete this comment if ($data[$this->uPrimary] != $this->uid && $data['x' . $this->uPrimary] != $this->uid && !in_array(self::$conf['namespaces'][$data['namespace']]['deletegroup'], $this->uGroups)) { return $this; } $this->forceDelete($id, $data); return $this; } /** * delete comment anyway * * Remove comment by id. Don't check anything * * @param string $id * @param array $data */ public function forceDelete($id, $data = null) { if (!$data) { try { $data = $this->load($id); } catch (WBException_Argument $e) { // cannot load comment return; } } $this->table->delete('comment', $id); if ($this->triggerEvent) { WBClass::load('WBEvent'); WBEvent::trigger('comment:deleted:' . $data['namespace'], 'Deleted comment for {NAMESPACE}:{XID}', $data); } } /** * save approved bit * * Mark comment as approved * * @param string $id * @param array $data */ protected function saveApprove($id, $data) { if (!$data['approved']) { $save = array( 'approved' => 1 ); $this->table->save('comment', $id, $save); } $this->approved = true; if ($this->triggerEvent) { WBEvent::trigger('comment:approved:' . $data['namespace'], 'Added comment for {NAMESPACE}:{XID}', $data); } } /** * load specific comment * * Auxiliary function to load existing comment * * @param string $id * @return array * @throws WBException_Argument */ protected function load($id) { $this->approved = false; $data = $this->table->get('comment', $id); if (count($data) != 1) { WBClass::load('WBException_Argument'); throw new WBException_Argument('Invalid comment id ' . $id, 3, __CLASS__); } $data = array_shift($data); // set namespace and xid $this->clause[0]['value'] = $data['namespace']; $this->clause[1]['value'] = $data['xid']; $this->xuid = $data['x' . $this->uPrimary]; return $data; } /** * initialize Filter List * * */ private function initFilter() { // only once if (is_array($this->filter)) { return; } // init filter list $this->filter = array(); $ns = $this->getNamespace(); if (!isset(self::$conf['namespaces'][$ns]['filter']) || !is_array(self::$conf['namespaces'][$ns]['filter'])) { return; } foreach (self::$conf['namespaces'][$ns]['filter'] as $clazz) { $this->filter[] = WBClass::create('WBDatasource_Comment_Filter_' . $clazz); } } /** * Get Filtered Clause List * * Use original clause and apply all filters + * @return array */ private function getFilteredClause() { $clause = $this->clause; foreach ($this->filter as $f) { $clause = $f->getClause($clause); } return $clause; } /** * Get Array of Custom Data * * @param array * @return array */ private function getCustomCommentData($comment) { $data = array(); $ns = $this->getNamespace(); if (!isset(self::$conf['namespaces'][$ns]['customfields']) || !is_array(self::$conf['namespaces'][$ns]['customfields'])) { return $data; } foreach (self::$conf['namespaces'][$ns]['customfields'] as $f) { if (isset($comment[$f])) { $data['comment' . $f] = $comment[$f]; } } return $data; } }