function getData() { $objects = DAO_KbArticle::search($this->params, $this->renderLimit, $this->renderPage, $this->renderSortBy, $this->renderSortAsc); return $objects; }
function writeResponse(DevblocksHttpResponse $response) { $tpl = DevblocksPlatform::getTemplateService(); $tpl_path = dirname(dirname(__FILE__)) . '/templates/'; $theme = DAO_CommunityToolProperty::get($this->getPortal(), UmScApp::PARAM_THEME, UmScApp::DEFAULT_THEME); if (!is_dir($tpl_path . 'portal/sc/themes/' . $theme)) { $theme = UmScApp::DEFAULT_THEME; } $umsession = $this->getSession(); $active_user = $umsession->getProperty('sc_login', null); $stack = $response->path; @($module = array_shift($stack)); switch ($module) { default: case 'home': $sHomeRss = DAO_CommunityToolProperty::get($this->getPortal(), UmScApp::PARAM_HOME_RSS, ''); $aHomeRss = !empty($sHomeRss) ? unserialize($sHomeRss) : array(); $feeds = array(); // [TODO] Implement a feed cache so we aren't bombing out foreach ($aHomeRss as $title => $url) { $feed = null; try { $feed = Zend_Feed::import($url); } catch (Exception $e) { } if (!empty($feed) && $feed->count()) { $feeds[] = array('name' => $title, 'feed' => $feed); } } $tpl->assign('feeds', $feeds); $tpl->display("file:{$tpl_path}portal/sc/internal/home/index.tpl"); break; case 'account': if (!$this->allow_logins || empty($active_user)) { break; } $address = DAO_Address::get($active_user->id); $tpl->assign('address', $address); $tpl->display("file:{$tpl_path}portal/sc/internal/account/index.tpl"); break; case 'kb': // KB Roots $sKbRoots = DAO_CommunityToolProperty::get($this->getPortal(), UmScApp::PARAM_KB_ROOTS, ''); $kb_roots = !empty($sKbRoots) ? unserialize($sKbRoots) : array(); $kb_roots_str = '0'; if (!empty($kb_roots)) { $kb_roots_str = implode(',', array_keys($kb_roots)); } switch (array_shift($stack)) { case 'article': if (empty($kb_roots)) { return; } $id = intval(array_shift($stack)); list($articles, $count) = DAO_KbArticle::search(array(new DevblocksSearchCriteria(SearchFields_KbArticle::ID, '=', $id), new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), -1, 0, null, null, false); if (!isset($articles[$id])) { break; } $article = DAO_KbArticle::get($id); $tpl->assign('article', $article); @($article_list = $umsession->getProperty(UmScApp::SESSION_ARTICLE_LIST, array())); if (!empty($article) && !isset($article_list[$id])) { DAO_KbArticle::update($article->id, array(DAO_KbArticle::VIEWS => ++$article->views)); $article_list[$id] = $id; $umsession->setProperty(UmScApp::SESSION_ARTICLE_LIST, $article_list); } $categories = DAO_KbCategory::getWhere(); $tpl->assign('categories', $categories); $cats = DAO_KbArticle::getCategoriesByArticleId($id); $breadcrumbs = array(); foreach ($cats as $cat_id) { if (!isset($breadcrumbs[$cat_id])) { $breadcrumbs[$cat_id] = array(); } $pid = $cat_id; while ($pid) { $breadcrumbs[$cat_id][] = $pid; $pid = $categories[$pid]->parent_id; } $breadcrumbs[$cat_id] = array_reverse($breadcrumbs[$cat_id]); // Remove any breadcrumbs not in this SC profile $pid = reset($breadcrumbs[$cat_id]); if (!isset($kb_roots[$pid])) { unset($breadcrumbs[$cat_id]); } } $tpl->assign('breadcrumbs', $breadcrumbs); $tpl->display("file:{$tpl_path}portal/sc/internal/kb/article.tpl"); break; default: case 'browse': @($root = intval(array_shift($stack))); $tpl->assign('root_id', $root); $categories = DAO_KbCategory::getWhere(); $tpl->assign('categories', $categories); $tree_map = DAO_KbCategory::getTreeMap(0); // Remove other top-level categories if (is_array($tree_map[0])) { foreach ($tree_map[0] as $child_id => $count) { if (!isset($kb_roots[$child_id])) { unset($tree_map[0][$child_id]); } } } // Remove empty categories if (is_array($tree_map[0])) { foreach ($tree_map as $node_id => $children) { foreach ($children as $child_id => $count) { if (empty($count)) { @($pid = $categories[$child_id]->parent_id); unset($tree_map[$pid][$child_id]); unset($tree_map[$child_id]); } } } } $tpl->assign('tree', $tree_map); // Breadcrumb // [TODO] API-ize inside Model_KbTree ? $breadcrumb = array(); $pid = $root; while (0 != $pid) { $breadcrumb[] = $pid; $pid = $categories[$pid]->parent_id; } $tpl->assign('breadcrumb', array_reverse($breadcrumb)); $tpl->assign('mid', @intval(ceil(count($tree_map[$root]) / 2))); // Articles if (!empty($root)) { list($articles, $count) = DAO_KbArticle::search(array(new DevblocksSearchCriteria(SearchFields_KbArticle::CATEGORY_ID, '=', $root), new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), -1, 0, null, null, false); } $tpl->assign('articles', $articles); $tpl->display("file:{$tpl_path}portal/sc/internal/kb/index.tpl"); break; } break; case 'answers': $query = rawurldecode(array_shift($stack)); $tpl->assign('query', $query); $sFnrSources = DAO_CommunityToolProperty::get($this->getPortal(), UmScApp::PARAM_FNR_SOURCES, ''); $aFnrSources = !empty($sFnrSources) ? unserialize($sFnrSources) : array(); if (!empty($query)) { // [JAS]: If we've been customized with specific sources, use them $where = !empty($aFnrSources) ? sprintf("%s IN (%s)", DAO_FnrExternalResource::ID, implode(',', array_keys($aFnrSources))) : sprintf("%s IN (-1)", DAO_FnrExternalResource::ID); $resources = DAO_FnrExternalResource::getWhere($where); $feeds = Model_FnrExternalResource::searchResources($resources, $query); $tpl->assign('feeds', $feeds); $fields = array(DAO_FnrQuery::QUERY => $query, DAO_FnrQuery::CREATED => time(), DAO_FnrQuery::SOURCE => $this->getPortal(), DAO_FnrQuery::NO_MATCH => empty($feeds) ? 1 : 0); DAO_FnrQuery::create($fields); } // KB $sKbRoots = DAO_CommunityToolProperty::get($this->getPortal(), UmScApp::PARAM_KB_ROOTS, ''); $kb_roots = !empty($sKbRoots) ? unserialize($sKbRoots) : array(); list($articles, $count) = DAO_KbArticle::search(array(array(DevblocksSearchCriteria::GROUP_OR, new DevblocksSearchCriteria(SearchFields_KbArticle::TITLE, 'fulltext', $query), new DevblocksSearchCriteria(SearchFields_KbArticle::CONTENT, 'fulltext', $query)), new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), 100, 0, null, null, true); $tpl->assign('articles', $articles); $tpl->display("file:{$tpl_path}portal/sc/internal/answers/index.tpl"); break; case 'contact': $response = array_shift($stack); $settings = CerberusSettings::getInstance(); $default_from = $settings->get(CerberusSettings::DEFAULT_REPLY_FROM); $tpl->assign('default_from', $default_from); switch ($response) { case 'confirm': $tpl->assign('last_opened', $umsession->getProperty('support.write.last_opened', '')); $tpl->display("file:{$tpl_path}portal/sc/internal/contact/confirm.tpl"); break; default: case 'step1': $umsession->setProperty('support.write.last_error', null); case 'step2': $sFrom = $umsession->getProperty('support.write.last_from', ''); $sSubject = $umsession->getProperty('support.write.last_subject', ''); $sNature = $umsession->getProperty('support.write.last_nature', ''); $sContent = $umsession->getProperty('support.write.last_content', ''); // $aLastFollowupQ = $umsession->getProperty('support.write.last_followup_q',''); $aLastFollowupA = $umsession->getProperty('support.write.last_followup_a', ''); $sError = $umsession->getProperty('support.write.last_error', ''); $tpl->assign('last_from', $sFrom); $tpl->assign('last_subject', $sSubject); $tpl->assign('last_nature', $sNature); $tpl->assign('last_content', $sContent); // $tpl->assign('last_followup_q', $aLastFollowupQ); $tpl->assign('last_followup_a', $aLastFollowupA); $tpl->assign('last_error', $sError); $sDispatch = DAO_CommunityToolProperty::get($this->getPortal(), UmScApp::PARAM_DISPATCH, ''); // $dispatch = !empty($sDispatch) ? (is_array($sDispatch) ? unserialize($sDispatch): array($sDispatch)) : array(); $dispatch = !empty($sDispatch) ? unserialize($sDispatch) : array(); $tpl->assign('dispatch', $dispatch); switch ($response) { default: // If there's only one situation, skip to step2 if (1 == count($dispatch)) { @($sNature = md5(key($dispatch))); $umsession->setProperty('support.write.last_nature', $sNature); reset($dispatch); } else { $tpl->display("file:{$tpl_path}portal/sc/internal/contact/step1.tpl"); break; } case 'step2': // Cache along with answers? if (is_array($dispatch)) { foreach ($dispatch as $k => $v) { if (md5($k) == $sNature) { $umsession->setProperty('support.write.last_nature_string', $k); $tpl->assign('situation', $k); $tpl->assign('situation_params', $v); break; } } } $ticket_fields = DAO_CustomField::getBySource('cerberusweb.fields.source.ticket'); $tpl->assign('ticket_fields', $ticket_fields); $tpl->display("file:{$tpl_path}portal/sc/internal/contact/step2.tpl"); break; } break; } break; // $tpl->display("file:${tpl_path}portal/sc/internal/contact/index.tpl"); // break; // $tpl->display("file:${tpl_path}portal/sc/internal/contact/index.tpl"); // break; case 'history': if (!$this->allow_logins || empty($active_user)) { break; } $mask = array_shift($stack); if (empty($mask)) { list($open_tickets) = DAO_Ticket::search(array(), array(new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_FIRST_WROTE_ID, '=', $active_user->id), new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_CLOSED, '=', 0)), -1, 0, SearchFields_Ticket::TICKET_UPDATED_DATE, false, false); $tpl->assign('open_tickets', $open_tickets); list($closed_tickets) = DAO_Ticket::search(array(), array(new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_FIRST_WROTE_ID, '=', $active_user->id), new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_CLOSED, '=', 1)), -1, 0, SearchFields_Ticket::TICKET_UPDATED_DATE, false, false); $tpl->assign('closed_tickets', $closed_tickets); $tpl->display("file:{$tpl_path}portal/sc/internal/history/index.tpl"); } else { // Secure retrieval (address + mask) list($tickets) = DAO_Ticket::search(array(), array(new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_MASK, '=', $mask), new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_FIRST_WROTE_ID, '=', $active_user->id)), 1, 0, null, null, false); $ticket = array_shift($tickets); // Security check (mask compare) if (0 == strcasecmp($ticket[SearchFields_Ticket::TICKET_MASK], $mask)) { $messages = DAO_Ticket::getMessagesByTicket($ticket[SearchFields_Ticket::TICKET_ID]); $messages = array_reverse($messages, true); $tpl->assign('ticket', $ticket); $tpl->assign('messages', $messages); $tpl->display("file:{$tpl_path}portal/sc/internal/history/display.tpl"); } } break; case 'register': if (!$this->allow_logins) { break; } @($step = array_shift($stack)); switch ($step) { case 'forgot': $tpl->display("file:{$tpl_path}portal/sc/internal/register/forgot.tpl"); break; case 'forgot2': $tpl->display("file:{$tpl_path}portal/sc/internal/register/forgot_confirm.tpl"); break; case 'confirm': $tpl->display("file:{$tpl_path}portal/sc/internal/register/confirm.tpl"); break; default: $tpl->display("file:{$tpl_path}portal/sc/internal/register/index.tpl"); break; } break; } // print_r($response); }
function doBulkUpdate($filter, $do, $ids = array()) { @set_time_limit(600); // [TODO] Temp! $change_fields = array(); $custom_fields = array(); // Make sure we have actions if (empty($do)) { return; } // Make sure we have checked items if we want a checked list if (0 == strcasecmp($filter, "checks") && empty($ids)) { return; } if (is_array($do)) { foreach ($do as $k => $v) { switch ($k) { // case 'x': // break; default: // Custom fields // if(substr($k,0,3)=="cf_") { // $custom_fields[substr($k,3)] = $v; // } break; } } } $pg = 0; if (empty($ids)) { do { list($objects, $null) = DAO_KbArticle::search($this->params, 100, $pg++, SearchFields_KbArticle::ID, true, false); $ids = array_merge($ids, array_keys($objects)); } while (!empty($objects)); } $batch_total = count($ids); for ($x = 0; $x <= $batch_total; $x += 100) { $batch_ids = array_slice($ids, $x, 100); if (!empty($change_fields)) { DAO_KbArticle::update($batch_ids, $change_fields); } // Category deltas if (isset($do['category_delta'])) { DAO_KbArticle::setCategories($batch_ids, $do['category_delta'], false); } // Custom Fields //self::_doBulkSetCustomFields(ChCustomFieldSource_Address::ID, $custom_fields, $batch_ids); unset($batch_ids); } unset($ids); }
private function _getListAction($path, $keychain) { @($root = DevblocksPlatform::importGPC($_REQUEST['root'], 'integer', 0)); // how many, and what page? @($p_page = DevblocksPlatform::importGPC($_REQUEST['p'], 'integer', 0)); @($limit = DevblocksPlatform::importGPC($_REQUEST['limit'], 'integer', 10)); // sort field and order @($sort = DevblocksPlatform::importGPC($_REQUEST['sort'], 'string', '')); $sort_field = SearchFields_KbArticle::ID; $sort_asc = true; switch ($sort) { case 'views': $sort_field = SearchFields_KbArticle::VIEWS; $sort_asc = false; break; case 'updated': $sort_field = SearchFields_KbArticle::UPDATED; $sort_asc = false; break; default: $sort_field = SearchFields_KbArticle::ID; $sort_asc = true; } $params = array(); if (0 != $root) { $params[] = new DevblocksSearchCriteria(SearchFields_KbArticle::CATEGORY_ID, '=', $root); } $params[SearchFields_KbArticle::TOP_CATEGORY_ID] = new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys(@$keychain->rights['acl_kb_topics'])); list($results, $null) = DAO_KbArticle::search($params, $limit, $p_page, $sort_field, $sort_asc, false); $this->_renderResults($results, SearchFields_KbArticle::getFields(), 'article', 'articles'); }
private function _renderRecentChangesRss($portal) { header("Content-Type: text/xml"); $xmlstr = <<<XML \t\t<rss version='2.0' xmlns:atom='http://www.w3.org/2005/Atom'> \t\t</rss> XML; $xml = new SimpleXMLElement($xmlstr); $translate = DevblocksPlatform::getTranslationService(); $url = DevblocksPlatform::getUrlService(); // Portal details $portal_name = DAO_CommunityToolProperty::get($portal, UmScApp::PARAM_PAGE_TITLE, ''); // Channel $channel = $xml->addChild('channel'); $channel->addChild('title', (!empty($portal_name) ? '[' . $portal_name . '] ' : '') . "Recently Changed Articles"); $channel->addChild('link', $url->write(sprintf('c=rss&kb=kb&a=recent_changes', $portal), true)); $channel->addChild('description', ''); // Limit topics to portal config @($topics = unserialize(DAO_CommunityToolProperty::get($portal, UmScKbController::PARAM_KB_ROOTS, ''))); if (empty($topics)) { return; } // Search Results list($results, $null) = DAO_KbArticle::search(array(SearchFields_KbArticle::TOP_CATEGORY_ID => new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($topics))), 25, 0, SearchFields_KbArticle::UPDATED, false, false); // [TODO] We should probably be building this feed with Zend Framework for compliance foreach ($results as $article) { $created = intval($article[SearchFields_KbArticle::UPDATED]); if (empty($created)) { $created = time(); } $eItem = $channel->addChild('item'); $escapedSubject = htmlspecialchars($article[SearchFields_KbArticle::TITLE], null, LANG_CHARSET_CODE); //filter out a couple non-UTF-8 characters (0xC and ESC) $escapedSubject = preg_replace("/[\f]/", '', $escapedSubject); $eTitle = $eItem->addChild('title', $escapedSubject); $eDesc = $eItem->addChild('description', htmlspecialchars($article[SearchFields_KbArticle::CONTENT], null, LANG_CHARSET_CODE)); $link = $url->write('c=kb&a=article&id=' . $article[SearchFields_KbArticle::ID], true); $eLink = $eItem->addChild('link', $link); $eDate = $eItem->addChild('pubDate', gmdate('D, d M Y H:i:s T', $created)); $eGuid = $eItem->addChild('guid', md5($escapedSubject . $link . $created)); $eGuid->addAttribute('isPermaLink', "false"); } echo $xml->asXML(); }
public function writeResponse(DevblocksHttpResponse $response) { $tpl = DevblocksPlatform::getTemplateService(); $tpl->cache_lifetime = "0"; $tpl->assign('tpl_path', dirname(__FILE__) . '/templates/'); $umsession = $this->getSession(); $stack = $response->path; $logo_url = DAO_CommunityToolProperty::get($this->getPortal(), self::PARAM_LOGO_URL, ''); $tpl->assign('logo_url', $logo_url); $page_title = DAO_CommunityToolProperty::get($this->getPortal(), self::PARAM_PAGE_TITLE, 'Knowledgebase'); $tpl->assign('page_title', $page_title); $captcha_enabled = DAO_CommunityToolProperty::get($this->getPortal(), self::PARAM_CAPTCHA_ENABLED, 1); $tpl->assign('captcha_enabled', $captcha_enabled); // KB Roots $sKbRoots = DAO_CommunityToolProperty::get($this->getPortal(), self::PARAM_KB_ROOTS, ''); $kb_roots = !empty($sKbRoots) ? unserialize($sKbRoots) : array(); $kb_roots_str = '0'; if (!empty($kb_roots)) { $kb_roots_str = implode(',', array_keys($kb_roots)); } // Usermeet Session if (null == ($fingerprint = parent::getFingerprint())) { die("A problem occurred."); } $tpl->assign('fingerprint', $fingerprint); switch (array_shift($stack)) { case 'rss': header("Content-type: application/rss+xml"); switch (array_shift($stack)) { case 'recent_changes': list($results, $null) = DAO_KbArticle::search(array(new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), 25, 0, SearchFields_KbArticle::UPDATED, false, false); if (is_array($results) && !empty($results)) { $full_articles = DAO_KbArticle::getWhere(sprintf("%s IN (%s)", DAO_KbArticle::ID, implode(',', array_keys($results)))); } $order = array_keys($results); $articles = array(); foreach ($order as $id) { $articles[$id] =& $full_articles[$id]; } $this->_writeArticlesAsRss($articles, $page_title); break; case 'most_popular': list($results, $null) = DAO_KbArticle::search(array(new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), 25, 0, SearchFields_KbArticle::VIEWS, false, false); if (is_array($results) && !empty($results)) { $full_articles = DAO_KbArticle::getWhere(sprintf("%s IN (%s)", DAO_KbArticle::ID, implode(',', array_keys($results)))); } $order = array_keys($results); $articles = array(); foreach ($order as $id) { $articles[$id] =& $full_articles[$id]; } $this->_writeArticlesAsRss($articles, $page_title); break; case 'search': $query = rawurldecode(array_shift($stack)); list($articles, $count) = DAO_KbArticle::search(array(array(DevblocksSearchCriteria::GROUP_OR, new DevblocksSearchCriteria(SearchFields_KbArticle::TITLE, 'fulltext', $query), new DevblocksSearchCriteria(SearchFields_KbArticle::CONTENT, 'fulltext', $query)), new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), 50, 0, null, null, true); if (!empty($articles)) { $articles = DAO_KbArticle::getWhere(sprintf("%s IN (%s)", DAO_KbArticle::ID, implode(',', array_keys($articles)))); } $this->_writeArticlesAsRss($articles, $page_title); break; // case 'article': // $id = intval(array_shift($stack)); // // // [TODO] Convert to KB categories // $articles = DAO_KbArticle::getWhere(sprintf("%s = %d AND %s = '%s'", // DAO_KbArticle::ID, // $id, // DAO_KbArticle::TITLE, // $this->getPortal() // )); // // $this->_writeArticlesAsRss($articles, $page_title); // // break; } break; case 'search': @($query = urldecode(array_shift($stack))); $session = $this->getSession(); if (!empty($query)) { $session->setProperty('last_query', $query); } else { $query = $session->getProperty('last_query', ''); } list($articles, $count) = DAO_KbArticle::search(array(array(DevblocksSearchCriteria::GROUP_OR, new DevblocksSearchCriteria(SearchFields_KbArticle::TITLE, 'fulltext', $query), new DevblocksSearchCriteria(SearchFields_KbArticle::CONTENT, 'fulltext', $query)), new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), 100, 0, null, null, true); $tpl->assign('query', $query); $tpl->assign('articles', $articles); $tpl->assign('count', $count); $tpl->display('file:' . dirname(__FILE__) . '/templates/portal/kb/search.tpl'); break; // case 'import': // if(empty($editor)) // break; // // $tpl->display('file:' . dirname(__FILE__) . '/templates/portal/kb/public_config/import.tpl'); // break; // case 'import': // if(empty($editor)) // break; // // $tpl->display('file:' . dirname(__FILE__) . '/templates/portal/kb/public_config/import.tpl'); // break; case 'article': // If no roots are enabled, no articles are visible if (empty($kb_roots)) { return; } $id = intval(array_shift($stack)); list($articles, $count) = DAO_KbArticle::search(array(new DevblocksSearchCriteria(SearchFields_KbArticle::ID, '=', $id), new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), -1, 0, null, null, false); if (!isset($articles[$id])) { break; } $article = DAO_KbArticle::get($id); $tpl->assign('article', $article); @($article_list = $umsession->getProperty(self::SESSION_ARTICLE_LIST, array())); if (!empty($article) && !isset($article_list[$id])) { DAO_KbArticle::update($article->id, array(DAO_KbArticle::VIEWS => ++$article->views)); $article_list[$id] = $id; $umsession->setProperty(self::SESSION_ARTICLE_LIST, $article_list); } $categories = DAO_KbCategory::getWhere(); $tpl->assign('categories', $categories); $cats = DAO_KbArticle::getCategoriesByArticleId($id); $breadcrumbs = array(); foreach ($cats as $cat_id) { if (!isset($breadcrumbs[$cat_id])) { $breadcrumbs[$cat_id] = array(); } $pid = $cat_id; while ($pid) { $breadcrumbs[$cat_id][] = $pid; $pid = $categories[$pid]->parent_id; } $breadcrumbs[$cat_id] = array_reverse($breadcrumbs[$cat_id]); // Remove any breadcrumbs not in this SC profile $pid = reset($breadcrumbs[$cat_id]); if (!isset($kb_roots[$pid])) { unset($breadcrumbs[$cat_id]); } } $tpl->assign('breadcrumbs', $breadcrumbs); $tpl->display('file:' . dirname(__FILE__) . '/templates/portal/kb/article.tpl'); break; case 'browse': default: // [TODO] Root @($root = intval(array_shift($stack))); $tpl->assign('root_id', $root); $categories = DAO_KbCategory::getWhere(); $tpl->assign('categories', $categories); $tree_map = DAO_KbCategory::getTreeMap(0); // Remove other top-level categories if (is_array($tree_map[0])) { foreach ($tree_map[0] as $child_id => $count) { if (!isset($kb_roots[$child_id])) { unset($tree_map[0][$child_id]); } } } // Remove empty categories if (is_array($tree_map[0])) { foreach ($tree_map as $node_id => $children) { foreach ($children as $child_id => $count) { if (empty($count)) { @($pid = $categories[$child_id]->parent_id); unset($tree_map[$pid][$child_id]); unset($tree_map[$child_id]); } } } } $tpl->assign('tree', $tree_map); // Breadcrumb // [TODO] API-ize inside Model_KbTree ? $breadcrumb = array(); $pid = $root; while (0 != $pid) { $breadcrumb[] = $pid; $pid = $categories[$pid]->parent_id; } $tpl->assign('breadcrumb', array_reverse($breadcrumb)); $tpl->assign('mid', @intval(ceil(count($tree_map[$root]) / 2))); // Articles $articles = array(); if (!empty($root)) { list($articles, $count) = DAO_KbArticle::search(array(new DevblocksSearchCriteria(SearchFields_KbArticle::CATEGORY_ID, '=', $root), new DevblocksSearchCriteria(SearchFields_KbArticle::TOP_CATEGORY_ID, 'in', array_keys($kb_roots))), -1, 0, null, null, false); $tpl->assign('articles', $articles); } $tpl->display('file:' . dirname(__FILE__) . '/templates/portal/kb/index.tpl'); break; } }