* @license PHP License * @package WB * @subpackage content */ /** * Load base class */ WBClass::load('WBContent'); /** * Content component: Blog * * Display and manage user blog * * @todo refactor using filter * @version 0.8.5 * @package WB * @subpackage content */ class WBContent_Blog extends WBContent { /** * my parameter list * @var array */ protected $config = array( 'action' => 'list', 'id' => '', 'title' => '', 'articletitle' => '%s - Blog', 'category' => '', 'goto' => '0', 'limit' => null, 'requiredgroup' => 'blogeditor', 'requiredgroupmanager' => 'blogadmin', 'translator' => 'no', 'translatorgroup' => 'nls-translator', 'vfs-user' => '0', 'clause' => array() ); /** * table * @var WBDatasource_Table */ protected $table; /** * list of blog entries * @var array */ protected $list = array(); /** * pager information * @var array */ protected $pagerInfo = array(); /** * foreign key identifing owning user * @var string */ protected $foreign; /** * blog tools * @var WBBlog_Tool */ private $blog; /** * NLS Saver * @var WBDatasource_NLS_Saver */ protected $nlsSaver; /** * User is allowed to edit content and translations * @const edit mode */ const EDIT_MODE_NORMAL = 1; /** * User may edit translations only * @const translation mode */ const EDIT_MODE_TRANSLATE = 2; /** * Current Edit Mode * @var int */ private $editMode = self::EDIT_MODE_NORMAL; /** * 2nd constructor * * Called after configuration was done */ protected function init() { $this->table = WBClass::create('WBDatasource_Table'); $params = array( 'table' => $this->table ); $this->blog = WBClass::create('WBBlog_Tool', $params); } /** * run * * run component * * @todo become user-aware for blog categories * @return array parameter list */ public function run() { // setup permissions $this->editMode = self::EDIT_MODE_NORMAL; $manager = $this->isUserInGroup($this->config['requiredgroupmanager']); $required = false; if ($manager) { $this->tmpl->addGlobalVar('blog_manager', 1); $required = true; } else { $required = $this->isUserInGroup($this->config['requiredgroup']); $allowed = array('display', 'list', 'edit'); if (!$required && in_array($this->config['translator'], array('auto', 'on')) && $this->isUserInGroup($this->config['translatorgroup'])) { $required = true; $this->editMode = self::EDIT_MODE_TRANSLATE; $allowed[] = 'categorylist'; $allowed[] = 'categoryedit'; } if (!in_array($this->config['action'], $allowed)) { $this->config['action'] = 'list'; } } if ($required) { $this->tmpl->addGlobalVar('blog_editor', 1); if (self::EDIT_MODE_NORMAL == $this->editMode) { $this->tmpl->addGlobalVar('blog_mode', 'edit'); } // shared VFS? if (!empty($this->config['vfs-user']) && strval($this->config['vfs-user']) != '0' ) { $this->sess->set('vfsfile_user', $this->config['vfs-user']); } else { $this->sess->clear('vfsfile_user'); } $this->foreign = $this->user->getId(); if ($manager || self::EDIT_MODE_TRANSLATE == $this->editMode) { $this->foreign = null; } } else { if (!in_array($this->config['action'], array('list', 'display'))) { $this->config['action'] = 'list'; } } if ('list' == $this->config['action']) { $this->config['id'] = ''; } if (0 == strncmp('category', $this->config['action'], 8)) { return $this->config; } if (!in_array($this->config['action'], array('add', 'edit', 'rm'))) { $this->loadArticles(); if (is_array($this->config['category'])) { $this->config['category'] = implode(',', $this->config['category']); } $this->tmpl->addGlobalVars($this->getBubbles()); return $this->config; } $this->loadArticles(); if (empty($this->list) && !in_array($this->config['action'], array('add', 'list'))) { $this->config['id'] = ''; $this->config['action'] = 'list'; return $this->config; } if (is_array($this->config['category'])) { $this->config['category'] = implode(',', $this->config['category']); } return $this->config; } /** * receive output * * fetch output of this content component * * @return string */ public function getString() { if (is_array($this->config['category'])) { $this->config['category'] = implode(',', $this->config['category']); } $this->tmpl->addGlobalVars($this->getBubbles()); $this->addConfigAsGlobalVars(); switch ($this->config['action']) { case 'categoryadd': $this->config['id'] = '__new'; // fall through case 'categoryedit': $cat = array(); if (!empty($this->config['id']) && '__new' != $this->config['id']) { $cat = $this->table->get(WBBlog::TABLE_BLOGCATEGORY, $this->config['id']); if (1 != count($cat)) { $cat = array(array()); } $cat = $cat[0]; } $this->table->switchTranslation(false); $this->startNlsSaver(WBBlog::TABLE_BLOGCATEGORY); $this->processForm('category', $cat); break; case 'categoryrm': $cat = $this->table->get(WBBlog::TABLE_BLOGCATEGORY, $this->config['id']); if (1 == count($cat)) { $cat = $cat[0]; $this->tmpl->addGlobalVars($cat); if ('yes' != $this->req->get('force', 'no')) { $this->loadTemplates('category-rm'); break; } $this->table->delete(WBBlog::TABLE_BLOGCATEGORY, $this->config['id']); $this->addAlert(WBContent::ALERT_TYPE_INFO, 'Category deleted', 'Category {TITLE} was deleted.', $cat); } // fall through case 'categorylist': $list = $this->table->get(WBBlog::TABLE_BLOGCATEGORY); $this->loadTemplates('category-list'); $this->list2Template($list, 'category_list'); break; case 'rm': // delete? $this->tmpl->addGlobalVars($this->list[0]); if ('yes' == $this->req->get('force', 'no')) { $this->table->delete(WBBlog::TABLE_BLOG, $this->config['id'], $this->foreign); $this->loadTemplates('rmDeleted'); $change = array('draft', 'deleted'); if (isset($this->list[0]['published']) && $this->list[0]['published']) { $change[0] = 'public'; } $eData = $this->list[0]; $eData['change'] = $change; WBEvent::trigger('blog:article:deleted', 'Deleted blog record {TITLE}.', $eData); break; } $this->loadTemplates('rm'); break; case 'add': case 'edit': $this->table->switchTranslation(false); $this->startNLSSaver(WBBlog::TABLE_BLOG); $this->processForm('edit', $this->list[0]); break; case 'display': $this->loadTemplates('display'); break; default: $this->tmpl->addGlobalVars($this->pagerInfo, 'pager_'); $this->loadTemplates('list'); break; } if ($this->tmpl->exists('list_entry')) { $this->tmpl->addRows('list_entry', $this->list); } return $this->tmpl->getParsedTemplate('snippet'); } /** * load blog articles * * @todo put bubble-stuff in parent class in a more generic manner */ protected function loadArticles() { $this->list = array(); if ('add' == $this->config['action']) { $this->list = array(array()); $this->config['id'] = ''; return; } if ('edit' == $this->config['action'] && empty($this->config['id'])) { $this->list = array(array()); $this->config['id'] = ''; $this->config['action'] = 'add'; return; } $clause = $this->config['clause']; if (!is_array($clause) || empty($clause)) { $clause = array(); } $this->injectSearch($clause); $this->injectCategory($clause); if (!$this->isUserInGroup($this->config['requiredgroupmanager'])) { // only published or user owned records $c = array(); $c[0] = array(); if ($this->user->isAuthenticated()) { $c[1] = array( 'field' => $this->table->getIdentifier('user'), 'value' => $this->user->getId() ); } // take care for drafts $c[0] = array( 'field' => 'published', 'value' => 1 ); $clause[] = array( 'type' => 'complex', 'bond' => 'or', 'clause' => $c ); // consider future records $c[0] = array( 'field' => 'created', 'relation' => 'le', 'value' => gmdate('Y-m-d H:i:s') ); $clause[] = array( 'type' => 'complex', 'bond' => 'or', 'clause' => $c ); } // try to load single blog entry if (!empty($this->config['id'])) { if (strstr($this->config['id'], '-')) { // load by date and check title if date has more than one record $created = strtotime($this->config['id']); $lClause = $clause; $lClause[] = array( 'field' => 'created', 'relation' => 'ge', 'value' => gmdate('Y-m-d', $created) ); $created += 86400; // plus one day 60 * 60 * 24 $lClause[] = array( 'field' => 'created', 'relation' => 'le', 'value' => gmdate('Y-m-d', $created) ); $options = array('limit' => 100); $this->list = $this->table->get('blog', null, $this->foreign, $lClause, $options); } else { $this->list = $this->table->get('blog', $this->config['id'], $this->foreign, $clause); } // fuzzy select: verify with title if (count($this->list) > 1 && !empty($this->config['title'])) { $title = strtolower(urldecode($this->config['title'])); foreach ($this->list as $l) { if (strtolower($l['title']) == $title) { $this->list = array($l); break; } $length = min(strlen($title), strlen($l['title'])); if (0 == strncmp(strtolower($l['title']), $title, $length)) { $this->list = array($l); break; } } } if (count($this->list) == 1) { $this->config['title'] = ''; // build URL using date instead of id $this->blog->loadArticleByData($this->list[0]); $this->list[0]['url'] = $this->blog->getArticleUrl(); $this->bubbles['url_type'] = 'article'; $this->bubbles['url'] = $this->list[0]['url']; $this->bubbles['title'] = sprintf($this->config['articletitle'], $this->list[0]['title']); $body = strip_tags($this->list[0]['body']); if (200 < strlen($body)) { $this->bubbles['description'] = substr($body, 0, 160) . '...'; } else { $this->bubbles['description'] = $body; } // $this->bubbles['author'] = $this->list[0]['forename']; $this->blog->addOpenGraph($this->bubbles, 'image'); $this->blog->addOpenGraph($this->bubbles, 'description'); $this->blog->addOpenGraph($this->bubbles, 'created'); switch ($this->config['action']) { case 'edit': case 'rm': case 'display': break; default: $this->config['action'] = 'display'; break; } return; } } $this->config['title'] = ''; $this->config['id'] = ''; $this->config['action'] = 'list'; $options = array(); if ($this->config['limit']) { $options['limit'] = $this->config['limit']; } $pager = $this->table->getPager($this->part . __CLASS__, WBBlog::TABLE_BLOG, null, $clause, $options); $this->pagerInfo = $pager->browse($this->config['goto']); $this->list = $pager->get(); $this->bubbles['url_type'] = 'blog'; $this->bubbles['url'] = $this->blog->getListUrl(); foreach($this->list as &$l) { $this->blog->loadArticleByData($l); $l['url'] = $this->blog->getArticleUrl(); } if (1 == $this->pagerInfo['total']) { $this->bubbles['url_type'] = 'article'; $this->bubbles['url'] = $this->list[0]['url']; $this->bubbles['title'] = $this->list[0]['title']; } } /** * Inject a category restriction * * @param array $clause */ private function injectCategory(&$clause) { if (!empty($this->config['category'])) { if (!is_array($this->config['category'])) { $this->config['category'] = explode(',', $this->config['category']); } $clause[] = array( 'field' => $this->table->getIdentifier('blogcategory'), 'relation' => 'in', 'value' => $this->config['category'] ); } } /** * Inject Search * * @param array $clause */ private function injectSearch(&$clause) { $query = trim($this->req->get('searchquery', '')); if (empty($query)) { return; } $tmplVars = array(); $query = urldecode($query); // normalize query $query = explode(' ', $query); $query = array_map('trim', $query); foreach ($query as $i => $q) { if (empty($q) || 3 > strlen($q)) { unset($query[$i]); } } $query = array_values($query); $searchquery = implode(' ', $query); $this->tmpl->addGlobalVar('search_query', $searchquery); $this->tmpl->addGlobalVar('search_query_url', urlencode($searchquery)); // search for strings in all searchfields $searchfields = array('title', 'body'); foreach ($query as $q) { $c = array(); foreach ($searchfields as $f) { $c[] = array( 'field' => $f, 'relation' => 'like', 'value' => $q ); } $clause[] = array( 'type' => 'complex', 'bond' => 'or', 'clause' => $c ); } } /** * Save blog entry * * Store record in database and add user id for new records * * @param patForms $form * @param array $values * @param return bool */ public function onEditValid($form, $values) { $id = $this->config['id']; $new = 0; if (empty($id)) { if (self::EDIT_MODE_NORMAL != $this->editMode) { $this->loadTemplates('editValid'); return false; } $new = 1; $id = '__new'; $uPrimary = $this->table->getIdentifier('user'); if (!isset($values[$uPrimary]) || empty($values[$uPrimary])) { $values[$uPrimary] = $this->user->getId(); } } if (self::EDIT_MODE_TRANSLATE == $this->editMode) { $old = $this->table->get(WBBlog::TABLE_BLOG, $this->config['id']); if (!empty($old)) { $values = array_merge($old[0], $values); } $this->tmpl->addGlobalVar('FORM_VALUES_TITLE_VALUE_CURRENT', $values['title']); } $this->nlsSaver->strip($values); if (self::EDIT_MODE_NORMAL == $this->editMode) { $this->config['id'] = $this->table->save(WBBlog::TABLE_BLOG, $id, $values); } $this->nlsSaver->setId($this->config['id']); $this->nlsSaver->save($values); $this->addAlert(WBContent::ALERT_TYPE_INFO, 'Article Saved', 'Blog Article {TITLE} saved.', $values); if (self::EDIT_MODE_NORMAL != $this->editMode) { $this->loadTemplates('editValid'); return false; } $change = array('draft', 'draft'); if (isset($this->list[0]['published']) && $this->list[0]['published']) { $change[0] = 'public'; } if (isset($values['published']) && $values['published']) { $change[1] = 'public'; } $values[$this->table->getIdentifier('blog')] = $values['id']; $this->list[0] = array_merge($this->list[0], $values); // trigger event $eData = $this->list[0]; $eData['new'] = $new; $eData['change']= $change; WBEvent::trigger('blog:article:saved', 'Saved blog record {TITLE}.', $eData); $this->loadTemplates('editValid'); return false; } /** * Save Category * * Store record in database and add user id for new records * * @param patForms $form * @param array $values * @param return bool */ public function onCategoryValid($form, $values) { if (self::EDIT_MODE_TRANSLATE == $this->editMode) { if ('__new' == $this->config['id']) { return true; } $old = $this->table->get(WBBlog::TABLE_BLOGCATEGORY, $this->config['id']); if (!empty($old)) { $values = array_merge($old[0], $values); } $this->tmpl->addGlobalVar('FORM_VALUES_TITLE_VALUE_CURRENT', $values['title']); } $this->nlsSaver->strip($values); if (self::EDIT_MODE_NORMAL == $this->editMode) { $this->config['id'] = $this->table->save(WBBlog::TABLE_BLOGCATEGORY, $this->config['id'], $values); } $this->nlsSaver->setId($this->config['id']); $this->nlsSaver->save($values); return true; } /** * What to Do When Rendering Form Element * * @param string form element name * @param array element data * @return bool true to go on, false to handle yourself */ protected function onFormElementRendered($name, $data) { if ($this->nlsSaver->formElement2Tmpl($name, $data, $this->tmpl)) { return false; } return true; } /** * Fetch List of Form Elements * * Use parent's method and add translators form elements * * @use WBDatasource_NLS_Saver::addFormElements() * @param string name of the xml- and template-filename * @return array $elements */ protected function getFormElementList($name) { $elements = parent::getFormElementList($name); $this->nlsSaver->addFormElements($elements); $nlsElements = $this->nlsSaver->getElementNames(); if (self::EDIT_MODE_TRANSLATE == $this->editMode) { foreach ($elements as $k => &$e) { if (isset($e['translate']) && 'no' == $e['translate']) { unset($elements[$k]); continue; } if (in_array($k, $nlsElements)) { continue; } $e['attributes']['required'] = 'no'; $e['attributes']['disabled'] = 'yes'; } } return $elements; } /** * location of form config * * Return sub directory where form element definitions are located * * @return string folder */ protected function getFormConfigDir() { return 'blog'; } /** * Start NLS Saver * * @param string table */ private function startNLSSaver($table) { if (empty($this->nlsSaver)) { $params = array( 'table' => $this->table ); $this->nlsSaver = WBClass::create('WBDatasource_NLS_Saver', $params); } $this->nlsSaver->setTableName($table); if (empty($this->config['id'])) { $this->nlsSaver->setId('__new'); } else { $this->nlsSaver->setId($this->config['id']); } $this->nlsSaver->enable(false); if (in_array($this->config['translator'], array('auto', 'on'))) { $this->nlsSaver->enable(true); } if (self::EDIT_MODE_NORMAL == $this->editMode) { return; } $list = $this->table->get('nlslangtranslator', null, $this->user->getId()); $lang = array(); foreach ($list as $l) { $lang[] = $l['lang']; } $this->nlsSaver->setAllowedLang($lang); } }