PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/components/com_content/models/article.php

https://bitbucket.org/eternaware/joomus
PHP | 323 lines | 208 code | 48 blank | 67 comment | 36 complexity | 551edb529e591ebd7e89b3f95574d509 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * @package Joomla.Site
  4. * @subpackage com_content
  5. *
  6. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. defined('_JEXEC') or die;
  10. /**
  11. * Content Component Article Model
  12. *
  13. * @package Joomla.Site
  14. * @subpackage com_content
  15. * @since 1.5
  16. */
  17. class ContentModelArticle extends JModelItem
  18. {
  19. /**
  20. * Model context string.
  21. *
  22. * @var string
  23. */
  24. protected $_context = 'com_content.article';
  25. /**
  26. * Method to auto-populate the model state.
  27. *
  28. * Note. Calling getState in this method will result in recursion.
  29. *
  30. * @since 1.6
  31. */
  32. protected function populateState()
  33. {
  34. $app = JFactory::getApplication('site');
  35. // Load state from the request.
  36. $pk = $app->input->getInt('id');
  37. $this->setState('article.id', $pk);
  38. $offset = $app->input->getUInt('limitstart');
  39. $this->setState('list.offset', $offset);
  40. // Load the parameters.
  41. $params = $app->getParams();
  42. $this->setState('params', $params);
  43. // TODO: Tune these values based on other permissions.
  44. $user = JFactory::getUser();
  45. if ((!$user->authorise('core.edit.state', 'com_content')) && (!$user->authorise('core.edit', 'com_content'))){
  46. $this->setState('filter.published', 1);
  47. $this->setState('filter.archived', 2);
  48. }
  49. }
  50. /**
  51. * Method to get article data.
  52. *
  53. * @param integer The id of the article.
  54. *
  55. * @return mixed Menu item data object on success, false on failure.
  56. */
  57. public function &getItem($pk = null)
  58. {
  59. $pk = (!empty($pk)) ? $pk : (int) $this->getState('article.id');
  60. if ($this->_item === null) {
  61. $this->_item = array();
  62. }
  63. if (!isset($this->_item[$pk])) {
  64. try {
  65. $db = $this->getDbo();
  66. $query = $db->getQuery(true);
  67. $query->select(
  68. $this->getState(
  69. 'item.select', 'a.id, a.asset_id, a.title, a.alias, a.introtext, a.fulltext, ' .
  70. // If badcats is not null, this means that the article is inside an unpublished category
  71. // In this case, the state is set to 0 to indicate Unpublished (even if the article state is Published)
  72. 'CASE WHEN badcats.id is null THEN a.state ELSE 0 END AS state, ' .
  73. 'a.catid, a.created, a.created_by, a.created_by_alias, ' .
  74. // use created if modified is 0
  75. 'CASE WHEN a.modified = ' . $db->q($db->getNullDate()) . ' THEN a.created ELSE a.modified END as modified, ' .
  76. 'a.modified_by, a.checked_out, a.checked_out_time, a.publish_up, a.publish_down, ' .
  77. 'a.images, a.urls, a.attribs, a.version, a.ordering, ' .
  78. 'a.metakey, a.metadesc, a.access, a.hits, a.metadata, a.featured, a.language, a.xreference'
  79. )
  80. );
  81. $query->from('#__content AS a');
  82. // Join on category table.
  83. $query->select('c.title AS category_title, c.alias AS category_alias, c.access AS category_access');
  84. $query->join('LEFT', '#__categories AS c on c.id = a.catid');
  85. // Join on user table.
  86. $query->select('u.name AS author');
  87. $query->join('LEFT', '#__users AS u on u.id = a.created_by');
  88. // Join on contact table
  89. $subQuery = $db->getQuery(true);
  90. $subQuery->select('contact.user_id, MAX(contact.id) AS id, contact.language');
  91. $subQuery->from('#__contact_details AS contact');
  92. $subQuery->where('contact.published = 1');
  93. $subQuery->group('contact.user_id, contact.language');
  94. $query->select('contact.id as contactid');
  95. $query->join('LEFT', '(' . $subQuery . ') AS contact ON contact.user_id = a.created_by');
  96. // Join over the categories to get parent category titles
  97. $query->select('parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias');
  98. $query->join('LEFT', '#__categories as parent ON parent.id = c.parent_id');
  99. // Join on voting table
  100. $query->select('ROUND(v.rating_sum / v.rating_count, 0) AS rating, v.rating_count as rating_count');
  101. $query->join('LEFT', '#__content_rating AS v ON a.id = v.content_id');
  102. $query->where('a.id = ' . (int) $pk);
  103. // Filter by start and end dates.
  104. $nullDate = $db->Quote($db->getNullDate());
  105. $date = JFactory::getDate();
  106. $nowDate = $db->Quote($date->toSql());
  107. $query->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')');
  108. $query->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
  109. // Join to check for category published state in parent categories up the tree
  110. // If all categories are published, badcats.id will be null, and we just use the article state
  111. $subquery = ' (SELECT cat.id as id FROM #__categories AS cat JOIN #__categories AS parent ';
  112. $subquery .= 'ON cat.lft BETWEEN parent.lft AND parent.rgt ';
  113. $subquery .= 'WHERE parent.extension = ' . $db->quote('com_content');
  114. $subquery .= ' AND parent.published <= 0 GROUP BY cat.id)';
  115. $query->join('LEFT OUTER', $subquery . ' AS badcats ON badcats.id = c.id');
  116. // Filter by published state.
  117. $published = $this->getState('filter.published');
  118. $archived = $this->getState('filter.archived');
  119. if (is_numeric($published)) {
  120. $query->where('(a.state = ' . (int) $published . ' OR a.state =' . (int) $archived . ')');
  121. }
  122. $db->setQuery($query);
  123. $data = $db->loadObject();
  124. if (empty($data)) {
  125. return JError::raiseError(404, JText::_('COM_CONTENT_ERROR_ARTICLE_NOT_FOUND'));
  126. }
  127. // Check for published state if filter set.
  128. if (((is_numeric($published)) || (is_numeric($archived))) && (($data->state != $published) && ($data->state != $archived))) {
  129. return JError::raiseError(404, JText::_('COM_CONTENT_ERROR_ARTICLE_NOT_FOUND'));
  130. }
  131. // Convert parameter fields to objects.
  132. $registry = new JRegistry;
  133. $registry->loadString($data->attribs);
  134. $data->params = clone $this->getState('params');
  135. $data->params->merge($registry);
  136. $registry = new JRegistry;
  137. $registry->loadString($data->metadata);
  138. $data->metadata = $registry;
  139. // Compute selected asset permissions.
  140. $user = JFactory::getUser();
  141. // Technically guest could edit an article, but lets not check that to improve performance a little.
  142. if (!$user->get('guest')) {
  143. $userId = $user->get('id');
  144. $asset = 'com_content.article.'.$data->id;
  145. // Check general edit permission first.
  146. if ($user->authorise('core.edit', $asset)) {
  147. $data->params->set('access-edit', true);
  148. }
  149. // Now check if edit.own is available.
  150. elseif (!empty($userId) && $user->authorise('core.edit.own', $asset)) {
  151. // Check for a valid user and that they are the owner.
  152. if ($userId == $data->created_by) {
  153. $data->params->set('access-edit', true);
  154. }
  155. }
  156. }
  157. // Compute view access permissions.
  158. if ($access = $this->getState('filter.access')) {
  159. // If the access filter has been set, we already know this user can view.
  160. $data->params->set('access-view', true);
  161. }
  162. else {
  163. // If no access filter is set, the layout takes some responsibility for display of limited information.
  164. $user = JFactory::getUser();
  165. $groups = $user->getAuthorisedViewLevels();
  166. if ($data->catid == 0 || $data->category_access === null) {
  167. $data->params->set('access-view', in_array($data->access, $groups));
  168. }
  169. else {
  170. $data->params->set('access-view', in_array($data->access, $groups) && in_array($data->category_access, $groups));
  171. }
  172. }
  173. $this->_item[$pk] = $data;
  174. }
  175. catch (Exception $e)
  176. {
  177. if ($e->getCode() == 404) {
  178. // Need to go thru the error handler to allow Redirect to work.
  179. JError::raiseError(404, $e->getMessage());
  180. }
  181. else {
  182. $this->setError($e);
  183. $this->_item[$pk] = false;
  184. }
  185. }
  186. }
  187. return $this->_item[$pk];
  188. }
  189. /**
  190. * Increment the hit counter for the article.
  191. *
  192. * @param int Optional primary key of the article to increment.
  193. *
  194. * @return boolean True if successful; false otherwise and internal error set.
  195. */
  196. public function hit($pk = 0)
  197. {
  198. $input = JFactory::getApplication()->input;
  199. $hitcount = $input->getInt('hitcount', 1);
  200. if ($hitcount)
  201. {
  202. $pk = (!empty($pk)) ? $pk : (int) $this->getState('article.id');
  203. $db = $this->getDbo();
  204. $db->setQuery(
  205. 'UPDATE #__content' .
  206. ' SET hits = hits + 1' .
  207. ' WHERE id = '.(int) $pk
  208. );
  209. try
  210. {
  211. $db->execute();
  212. }
  213. catch (RuntimeException $e)
  214. {
  215. $this->setError($e->getMessage());
  216. return false;
  217. }
  218. }
  219. return true;
  220. }
  221. public function storeVote($pk = 0, $rate = 0)
  222. {
  223. if ( $rate >= 1 && $rate <= 5 && $pk > 0 )
  224. {
  225. $userIP = $_SERVER['REMOTE_ADDR'];
  226. $db = $this->getDbo();
  227. $db->setQuery(
  228. 'SELECT *' .
  229. ' FROM #__content_rating' .
  230. ' WHERE content_id = '.(int) $pk
  231. );
  232. $rating = $db->loadObject();
  233. if (!$rating)
  234. {
  235. // There are no ratings yet, so lets insert our rating
  236. $db->setQuery(
  237. 'INSERT INTO #__content_rating ( content_id, lastip, rating_sum, rating_count )' .
  238. ' VALUES ( '.(int) $pk.', '.$db->Quote($userIP).', '.(int) $rate.', 1 )'
  239. );
  240. try
  241. {
  242. $db->execute();
  243. }
  244. catch (RuntimeException $e)
  245. {
  246. $this->setError($e->getMessage);
  247. return false;
  248. }
  249. } else {
  250. if ($userIP != ($rating->lastip))
  251. {
  252. $db->setQuery(
  253. 'UPDATE #__content_rating' .
  254. ' SET rating_count = rating_count + 1, rating_sum = rating_sum + '.(int) $rate.', lastip = '.$db->Quote($userIP) .
  255. ' WHERE content_id = '.(int) $pk
  256. );
  257. try
  258. {
  259. $db->execute();
  260. }
  261. catch (RuntimeException $e)
  262. {
  263. $this->setError($e->getMessage);
  264. return false;
  265. }
  266. } else {
  267. return false;
  268. }
  269. }
  270. return true;
  271. }
  272. JError::raiseWarning('SOME_ERROR_CODE', JText::sprintf('COM_CONTENT_INVALID_RATING', $rate), "JModelArticle::storeVote($rate)");
  273. return false;
  274. }
  275. }