/** * Displays published articles for a given category (if any) * * @param string $category * @param bool $catSelector Toggles the category selector * @return string */ protected function displayArticles($category = false, $catSelector = true) { $this->setOutputType(self::_OT_CONTENT_INDEX); if (empty($category)) { $this->setTitle(t('Latest articles')); $categories = $this->_model()->getAllCategories(); $cid = null; } else { /** * Attempt to get the single article category details, and check permission */ try { $category = $this->_model()->getCategory($category, false); $this->setTitle($category['title']); $categories = array($category['id'] => $category); $cid = $category['id']; $resource = 'article-cat-' . $category['id']; if (!$this->_acl->resourceExists($resource) || !$this->_acl->check($resource)) { throw new Module_NoPermission(); } } catch (Article_CatNoExist $e) { throw new Module_ControllerNoExist(); } } /** * Check how many to display per page, and what page we are on */ try { $perPage = abs($this->_config->get('article/per_page')); } catch (Input_KeyNoExist $e) { $perPage = 12; } if ($this->inSector('SC') && $this->_input->has('get', 'page')) { $curPage = abs($this->_input->get('page') - 1); } else { $curPage = 0; } // Get the required articles and parse their first article part body $maxDisplayAge = $this->_config->get('article/max_display_age'); $articles = array(); foreach ($this->_model()->getAllArticles($perPage, $curPage * $perPage, $cid, false, $maxDisplayAge) as $tmpArticle) { if (isset($categories[$tmpArticle['cat_id']])) { $parts = $this->_model()->getArticleParts($tmpArticle['id']); $firstPart = current($parts); $editor = new Editor($firstPart['body']); $editor->setContentUrl($this->_router->makeUrl('article', 'view', $tmpArticle['identifier'])); $tmpArticle['body'] = $editor->parse(true); $tmpArticle['category_title'] = $categories[$tmpArticle['cat_id']]['title']; $tmpArticle['category_identifier'] = $categories[$tmpArticle['cat_id']]['identifier']; $articles[] = $tmpArticle; } } $articleCount = $this->_model()->getCount(); if ($articleCount > 0) { $pagination = new Pagination($articleCount, $perPage); } // Build up the view $view = $this->loadView('index/latest.html'); $view->assign(array('META_FORMAT' => $this->getMetaFormat($this->_config->get('article/meta_format')), 'CAT_DETAILS' => $cid ? $category : null)); $view->assignHtml(array('ARTICLES' => $articles, 'PAGINATION' => isset($pagination) ? $pagination->build() : null)); if ($cid == false && $catSelector) { /** Prepend the category selector */ $catSelectorView = $this->loadView('index/category_selector.html'); $catSelectorView->assign(array('CATEGORIES' => $categories)); return $catSelectorView->getOutput() . $view->getOutput(true); } else { return $view->getOutput(true); } }
/** * Magic method, allows for shorter URLs. Display the specified * contact form to the user. * * @param string $name * @param array $args * @return mixed */ public function __call($name, array $args) { $this->setTitle(t('Contact')); $this->setOutputType(self::_OT_COLLECTIVE); // Get the correct form identifier to display try { $contact = $this->_model()->getForm(substr($name, 0, -7), false); } catch (Contact_NoExist $e) { throw new Module_ControllerNoExist(); } if (!$this->_acl->check('contact-form-' . $contact['id'])) { throw new Module_NoPermission(); } $this->setTitle($contact['name']); /** * Prepare form validation, if needed */ $fields = $this->_model()->getFormFields($contact['id']); if ($fields) { $form = new View_form('contact.html', 'contact'); $form->caseSensitive()->antispam(true); $form->addElement('contact/email', $this->_session->getUser('email'), t('Email address'), new Validator_Email()); foreach ($fields as &$tmpField) { $tmpField['options'] = zula_split_config($tmpField['options']); // Use correct validation for the given types. switch ($tmpField['type']) { case 'textbox': case 'password': $validator = new Validator_Length(1, 300); break; case 'textarea': $validator = new Validator_Length(1, 3000); break; case 'radio': case 'select': case 'checkbox': $validator = new Validator_InArray(array_values($tmpField['options'])); break; default: $validator = null; } $form->addElement('contact/fields/' . $tmpField['id'], null, $tmpField['name'], $validator, (bool) $tmpField['required']); } if ($form->hasInput() && $form->isValid()) { /** * Send out the contact form email */ $mailBody = $this->loadView('email_body.txt'); $mailBody->assign(array('form' => $contact, 'fields' => $fields, 'email' => $form->getValues('contact/email'))); $mailBody->assignHtml(array('contact' => $form->getValues('contact'))); try { $message = new Email_message(sprintf(t('Contact form "%s"'), $contact['name']), $mailBody->getOutput(), 'text/plain'); $message->setTo($contact['email']); $message->setReplyTo($form->getValues('contact/email')); $email = new Email(); $email->send($message); $this->_event->success(t('Contact form sent successfully')); } catch (Email_Exception $e) { $this->_event->error(t('Sorry, there was a technical error while sending the contact form')); $this->_log->message($e->getMessage(), Log::L_WARNING); } return zula_redirect($this->_router->getParsedUrl()); } } else { $form = $this->loadView('contact.html'); } // Parse the body $editor = new Editor($contact['body']); unset($contact['body']); $form->assignHtml(array('body' => $editor->parse())); $form->assign(array('details' => $contact, 'fields' => $fields)); return $form->getOutput(); }
/** * Prepares a description by cutting it down to a max length, removing * possible shebang (from editor) and other small jazzy things * * @param string $str * @param string $link * @return string */ protected function prepareDescription($str, $link) { $editor = new Editor($str); $editor->preParse(); $editor->setContentUrl($link); return $editor->parse(true); }
/** * Gets all comments, or for a specific request path. Can also * restrict the result set returned. * * @param string $requestPath * @param string $status * @param int $limit * @param int $offset * @param string $order * @return array */ public function get($requestPath = null, $status = self::_ACCEPTED, $limit = 0, $offset = 0, $order = 'ASC') { $statement = 'SELECT SQL_CALC_FOUND_ROWS * FROM {PREFIX}mod_comments'; $params = array(); // Add in the WHERE $where = 'WHERE'; if ($requestPath !== null) { $where .= ' url LIKE :url'; $params[':url'] = $requestPath . '%'; } if ($status != self::_ALL) { $tmp = ' status = :status'; if ($where != 'WHERE') { $tmp = ' AND' . $tmp; } $where .= $tmp; $params[':status'] = $status; } if ($where != 'WHERE') { $statement .= ' ' . $where; } if (strtoupper($order) != 'ASC') { $order = 'DESC'; } // Check if we need to limit the result set if ($limit != 0 || $offset != 0) { $comments = array(); $statement .= ' ORDER BY date ' . $order; if ($limit > 0) { $statement .= ' LIMIT :limit'; $params[':limit'] = $limit; } else { if (empty($limit) && !empty($offset)) { $statement .= ' LIMIT 1000000'; } } if ($offset > 0) { $statement .= ' OFFSET :offset'; $params[':offset'] = $offset; } // Prepare and execute query $pdoSt = $this->_sql->prepare($statement); foreach ($params as $ident => $val) { if ($ident == ':url' || $ident == ':status') { $pdoSt->bindValue($ident, $val); } else { $pdoSt->bindValue($ident, (int) $val, PDO::PARAM_INT); } } $pdoSt->execute(); } else { /** * Get all comments of a certain status. Only cache accepted comments */ if ($status == self::_ACCEPTED) { $cacheKey = 'comments'; if ($requestPath !== null) { $cacheKey .= '_' . zula_hash($requestPath); } } else { $cacheKey = null; } if (!($comments = $this->_cache->get($cacheKey))) { $comments = array(); $statement .= ' ORDER BY date ' . $order; $pdoSt = $this->_sql->prepare($statement); $pdoSt->execute($params); } } if (isset($pdoSt)) { foreach ($pdoSt->fetchAll(PDO::FETCH_ASSOC) as $row) { $editor = new Editor("#!plaintext\n" . $row['body'], array('nofollow' => true)); $row['body'] = $editor->parse(false, true); $comments[$row['id']] = $row; } if (isset($cacheKey)) { $this->_cache->add($cacheKey, $comments); } $pdoSt->closeCursor(); $query = $this->_sql->query('SELECT FOUND_ROWS()'); $this->commentCount = $query->fetch(PDO::FETCH_COLUMN); $query->closeCursor(); } else { $this->commentCount = count($comments); } return $comments; }
/** * Magic method - allows for shorter URL's eg: * /article/view/clean-title * * @param string $name * @param array $args * @return string */ public function __call($name, $args) { $this->setOutputType(self::_OT_CONTENT_DYNAMIC); try { $article = $this->_model()->getArticle(substr($name, 0, -7), false); $this->setTitle($article['title']); $category = $this->_model()->getCategory($article['cat_id']); // Check permission to parent category $resource = 'article-cat-' . $category['id']; if (!$this->_acl->resourceExists($resource) || !$this->_acl->check($resource)) { throw new Module_NoPermission(); } else { if (!$article['published']) { throw new Module_ControllerNoExist(); } } /** * Gather all parts for this article, and check the requested part actually exists */ try { $part = abs($this->_input->get('part')); } catch (Input_KeyNoExist $e) { $part = 0; } $articleParts = array_values($this->_model()->getArticleParts($article['id'], false)); # Done to reindex array try { // Get details for the correct part if (empty($part)) { $partId = $articleParts[0]['id']; } else { if (isset($articleParts[$part - 1]['id'])) { $partId = $articleParts[$part - 1]['id']; } else { throw new Article_PartNoExist($part); } } $requestedPart = $this->_model()->getPart($partId); $editor = new Editor($requestedPart['body']); $body = $editor->parse(); } catch (Article_PartNoExist $e) { throw new Module_ControllerNoExist(); } /** * Build up pagination and the main view file */ try { $curPage = abs($this->_input->get('part') - 1); } catch (Input_KeyNoExist $e) { $curPage = 0; } $pagination = new Pagination(count($articleParts), 1, 'part'); if (count($articleParts) > 1) { $this->addAsset('js/jumpbox.js'); } $view = $this->loadView('view/article.html'); $view->assign(array('META_FORMAT' => $this->getMetaFormat($this->_config->get('article/meta_format')), 'ARTICLE' => $article, 'REQUESTED_PART' => $requestedPart, 'ARTICLE_PARTS' => $articleParts, 'CATEGORY' => $category)); $view->assignHtml(array('BODY' => $body, 'PAGINATION' => $pagination->build())); return $view->getOutput(true); } catch (Article_NoExist $e) { throw new Module_ControllerNoExist(); } }
/** * Makes the index/contents page for a page. * * This is similar to what is found at the start of a book. * It will create a string in Wiki syntax, as it's the * eaasiest way for creating this list. * * @param int $pid * @return string */ protected function makePageIndex($pid) { $children = $this->_model()->getChildren($pid, true); if (!empty($children)) { $wikiPage = "#!mediawiki\n===" . t('Table of contents') . "===\n"; foreach ($children as $child) { $pageLink = $this->_router->makeUrl('page', 'index', $child['identifier']); $wikiPage .= str_repeat('#', $child['depth'] + 1) . '[[' . $pageLink . '|' . $child['title'] . ']]' . "\n"; } $editor = new Editor($wikiPage); return $editor->parse(); } else { return ''; } }