PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/administrator/components/com_content/models/article.php

https://github.com/CCI-Studios/Wee-Magazine
PHP | 545 lines | 304 code | 76 blank | 165 comment | 53 complexity | 65a7ca8eb522852d54b888e2f1e12755 MD5 | raw file
  1. <?php
  2. /**
  3. * @package Joomla.Administrator
  4. * @subpackage com_content
  5. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  6. * @license GNU General Public License version 2 or later; see LICENSE.txt
  7. */
  8. // No direct access
  9. defined('_JEXEC') or die;
  10. jimport('joomla.application.component.modeladmin');
  11. require_once JPATH_COMPONENT_ADMINISTRATOR.'/helpers/content.php';
  12. /**
  13. * Item Model for an Article.
  14. *
  15. * @package Joomla.Administrator
  16. * @subpackage com_content
  17. * @since 1.6
  18. */
  19. class ContentModelArticle extends JModelAdmin
  20. {
  21. /**
  22. * @var string The prefix to use with controller messages.
  23. * @since 1.6
  24. */
  25. protected $text_prefix = 'COM_CONTENT';
  26. /**
  27. * Batch copy items to a new category or current.
  28. *
  29. * @param integer $value The new category.
  30. * @param array $pks An array of row IDs.
  31. * @param array $contexts An array of item contexts.
  32. *
  33. * @return mixed An array of new IDs on success, boolean false on failure.
  34. *
  35. * @since 11.1
  36. */
  37. protected function batchCopy($value, $pks, $contexts)
  38. {
  39. $categoryId = (int) $value;
  40. $table = $this->getTable();
  41. $i = 0;
  42. // Check that the category exists
  43. if ($categoryId)
  44. {
  45. $categoryTable = JTable::getInstance('Category');
  46. if (!$categoryTable->load($categoryId))
  47. {
  48. if ($error = $categoryTable->getError())
  49. {
  50. // Fatal error
  51. $this->setError($error);
  52. return false;
  53. }
  54. else
  55. {
  56. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
  57. return false;
  58. }
  59. }
  60. }
  61. if (empty($categoryId))
  62. {
  63. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
  64. return false;
  65. }
  66. // Check that the user has create permission for the component
  67. $extension = JFactory::getApplication()->input->get('option', '');
  68. $user = JFactory::getUser();
  69. if (!$user->authorise('core.create', $extension . '.category.' . $categoryId))
  70. {
  71. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE'));
  72. return false;
  73. }
  74. // Parent exists so we let's proceed
  75. while (!empty($pks))
  76. {
  77. // Pop the first ID off the stack
  78. $pk = array_shift($pks);
  79. $table->reset();
  80. // Check that the row actually exists
  81. if (!$table->load($pk))
  82. {
  83. if ($error = $table->getError())
  84. {
  85. // Fatal error
  86. $this->setError($error);
  87. return false;
  88. }
  89. else
  90. {
  91. // Not fatal error
  92. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk));
  93. continue;
  94. }
  95. }
  96. // Alter the title & alias
  97. $data = $this->generateNewTitle($categoryId, $table->alias, $table->title);
  98. $table->title = $data['0'];
  99. $table->alias = $data['1'];
  100. // Reset the ID because we are making a copy
  101. $table->id = 0;
  102. // New category ID
  103. $table->catid = $categoryId;
  104. // TODO: Deal with ordering?
  105. //$table->ordering = 1;
  106. // Get the featured state
  107. $featured = $table->featured;
  108. // Check the row.
  109. if (!$table->check())
  110. {
  111. $this->setError($table->getError());
  112. return false;
  113. }
  114. // Store the row.
  115. if (!$table->store())
  116. {
  117. $this->setError($table->getError());
  118. return false;
  119. }
  120. // Get the new item ID
  121. $newId = $table->get('id');
  122. // Add the new ID to the array
  123. $newIds[$i] = $newId;
  124. $i++;
  125. // Check if the article was featured and update the #__content_frontpage table
  126. if ($featured == 1)
  127. {
  128. $db = $this->getDbo();
  129. $query = $db->getQuery(true);
  130. $query->insert($db->quoteName('#__content_frontpage'));
  131. $query->values($newId . ', 0');
  132. $db->setQuery($query);
  133. $db->query();
  134. }
  135. }
  136. // Clean the cache
  137. $this->cleanCache();
  138. return $newIds;
  139. }
  140. /**
  141. * Method to test whether a record can be deleted.
  142. *
  143. * @param object $record A record object.
  144. *
  145. * @return boolean True if allowed to delete the record. Defaults to the permission set in the component.
  146. * @since 1.6
  147. */
  148. protected function canDelete($record)
  149. {
  150. if (!empty($record->id)) {
  151. if ($record->state != -2) {
  152. return ;
  153. }
  154. $user = JFactory::getUser();
  155. return $user->authorise('core.delete', 'com_content.article.'.(int) $record->id);
  156. }
  157. }
  158. /**
  159. * Method to test whether a record can have its state edited.
  160. *
  161. * @param object $record A record object.
  162. *
  163. * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component.
  164. * @since 1.6
  165. */
  166. protected function canEditState($record)
  167. {
  168. $user = JFactory::getUser();
  169. // Check for existing article.
  170. if (!empty($record->id)) {
  171. return $user->authorise('core.edit.state', 'com_content.article.'.(int) $record->id);
  172. }
  173. // New article, so check against the category.
  174. elseif (!empty($record->catid)) {
  175. return $user->authorise('core.edit.state', 'com_content.category.'.(int) $record->catid);
  176. }
  177. // Default to component settings if neither article nor category known.
  178. else {
  179. return parent::canEditState('com_content');
  180. }
  181. }
  182. /**
  183. * Prepare and sanitise the table data prior to saving.
  184. *
  185. * @param JTable A JTable object.
  186. *
  187. * @return void
  188. * @since 1.6
  189. */
  190. protected function prepareTable(&$table)
  191. {
  192. // Set the publish date to now
  193. $db = $this->getDbo();
  194. if($table->state == 1 && intval($table->publish_up) == 0) {
  195. $table->publish_up = JFactory::getDate()->toSql();
  196. }
  197. // Increment the content version number.
  198. $table->version++;
  199. // Reorder the articles within the category so the new article is first
  200. if (empty($table->id)) {
  201. $table->reorder('catid = '.(int) $table->catid.' AND state >= 0');
  202. }
  203. }
  204. /**
  205. * Returns a Table object, always creating it.
  206. *
  207. * @param type The table type to instantiate
  208. * @param string A prefix for the table class name. Optional.
  209. * @param array Configuration array for model. Optional.
  210. *
  211. * @return JTable A database object
  212. */
  213. public function getTable($type = 'Content', $prefix = 'JTable', $config = array())
  214. {
  215. return JTable::getInstance($type, $prefix, $config);
  216. }
  217. /**
  218. * Method to get a single record.
  219. *
  220. * @param integer The id of the primary key.
  221. *
  222. * @return mixed Object on success, false on failure.
  223. */
  224. public function getItem($pk = null)
  225. {
  226. if ($item = parent::getItem($pk)) {
  227. // Convert the params field to an array.
  228. $registry = new JRegistry;
  229. $registry->loadString($item->attribs);
  230. $item->attribs = $registry->toArray();
  231. // Convert the metadata field to an array.
  232. $registry = new JRegistry;
  233. $registry->loadString($item->metadata);
  234. $item->metadata = $registry->toArray();
  235. // Convert the images field to an array.
  236. $registry = new JRegistry;
  237. $registry->loadString($item->images);
  238. $item->images = $registry->toArray();
  239. // Convert the urls field to an array.
  240. $registry = new JRegistry;
  241. $registry->loadString($item->urls);
  242. $item->urls = $registry->toArray();
  243. $item->articletext = trim($item->fulltext) != '' ? $item->introtext . "<hr id=\"system-readmore\" />" . $item->fulltext : $item->introtext;
  244. }
  245. return $item;
  246. }
  247. /**
  248. * Method to get the record form.
  249. *
  250. * @param array $data Data for the form.
  251. * @param boolean $loadData True if the form is to load its own data (default case), false if not.
  252. *
  253. * @return mixed A JForm object on success, false on failure
  254. * @since 1.6
  255. */
  256. public function getForm($data = array(), $loadData = true)
  257. {
  258. // Get the form.
  259. $form = $this->loadForm('com_content.article', 'article', array('control' => 'jform', 'load_data' => $loadData));
  260. if (empty($form)) {
  261. return false;
  262. }
  263. $jinput = JFactory::getApplication()->input;
  264. // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first.
  265. if ($jinput->get('a_id'))
  266. {
  267. $id = $jinput->get('a_id', 0);
  268. }
  269. // The back end uses id so we use that the rest of the time and set it to 0 by default.
  270. else
  271. {
  272. $id = $jinput->get('id', 0);
  273. }
  274. // Determine correct permissions to check.
  275. if ($this->getState('article.id'))
  276. {
  277. $id = $this->getState('article.id');
  278. // Existing record. Can only edit in selected categories.
  279. $form->setFieldAttribute('catid', 'action', 'core.edit');
  280. // Existing record. Can only edit own articles in selected categories.
  281. $form->setFieldAttribute('catid', 'action', 'core.edit.own');
  282. }
  283. else
  284. {
  285. // New record. Can only create in selected categories.
  286. $form->setFieldAttribute('catid', 'action', 'core.create');
  287. }
  288. $user = JFactory::getUser();
  289. // Check for existing article.
  290. // Modify the form based on Edit State access controls.
  291. if ($id != 0 && (!$user->authorise('core.edit.state', 'com_content.article.'.(int) $id))
  292. || ($id == 0 && !$user->authorise('core.edit.state', 'com_content'))
  293. )
  294. {
  295. // Disable fields for display.
  296. $form->setFieldAttribute('featured', 'disabled', 'true');
  297. $form->setFieldAttribute('ordering', 'disabled', 'true');
  298. $form->setFieldAttribute('publish_up', 'disabled', 'true');
  299. $form->setFieldAttribute('publish_down', 'disabled', 'true');
  300. $form->setFieldAttribute('state', 'disabled', 'true');
  301. // Disable fields while saving.
  302. // The controller has already verified this is an article you can edit.
  303. $form->setFieldAttribute('featured', 'filter', 'unset');
  304. $form->setFieldAttribute('ordering', 'filter', 'unset');
  305. $form->setFieldAttribute('publish_up', 'filter', 'unset');
  306. $form->setFieldAttribute('publish_down', 'filter', 'unset');
  307. $form->setFieldAttribute('state', 'filter', 'unset');
  308. }
  309. return $form;
  310. }
  311. /**
  312. * Method to get the data that should be injected in the form.
  313. *
  314. * @return mixed The data for the form.
  315. * @since 1.6
  316. */
  317. protected function loadFormData()
  318. {
  319. // Check the session for previously entered form data.
  320. $data = JFactory::getApplication()->getUserState('com_content.edit.article.data', array());
  321. if (empty($data)) {
  322. $data = $this->getItem();
  323. // Prime some default values.
  324. if ($this->getState('article.id') == 0) {
  325. $app = JFactory::getApplication();
  326. $data->set('catid', JRequest::getInt('catid', $app->getUserState('com_content.articles.filter.category_id')));
  327. }
  328. }
  329. return $data;
  330. }
  331. /**
  332. * Method to save the form data.
  333. *
  334. * @param array The form data.
  335. *
  336. * @return boolean True on success.
  337. * @since 1.6
  338. */
  339. public function save($data)
  340. {
  341. if (isset($data['images']) && is_array($data['images'])) {
  342. $registry = new JRegistry;
  343. $registry->loadArray($data['images']);
  344. $data['images'] = (string)$registry;
  345. }
  346. if (isset($data['urls']) && is_array($data['urls'])) {
  347. $registry = new JRegistry;
  348. $registry->loadArray($data['urls']);
  349. $data['urls'] = (string)$registry;
  350. }
  351. // Alter the title for save as copy
  352. if (JRequest::getVar('task') == 'save2copy') {
  353. list($title, $alias) = $this->generateNewTitle($data['catid'], $data['alias'], $data['title']);
  354. $data['title'] = $title;
  355. $data['alias'] = $alias;
  356. }
  357. if (parent::save($data)) {
  358. if (isset($data['featured'])) {
  359. $this->featured($this->getState($this->getName().'.id'), $data['featured']);
  360. }
  361. return true;
  362. }
  363. return false;
  364. }
  365. /**
  366. * Method to toggle the featured setting of articles.
  367. *
  368. * @param array The ids of the items to toggle.
  369. * @param int The value to toggle to.
  370. *
  371. * @return boolean True on success.
  372. */
  373. public function featured($pks, $value = 0)
  374. {
  375. // Sanitize the ids.
  376. $pks = (array) $pks;
  377. JArrayHelper::toInteger($pks);
  378. if (empty($pks)) {
  379. $this->setError(JText::_('COM_CONTENT_NO_ITEM_SELECTED'));
  380. return false;
  381. }
  382. $table = $this->getTable('Featured', 'ContentTable');
  383. try {
  384. $db = $this->getDbo();
  385. $db->setQuery(
  386. 'UPDATE #__content' .
  387. ' SET featured = '.(int) $value.
  388. ' WHERE id IN ('.implode(',', $pks).')'
  389. );
  390. if (!$db->query()) {
  391. throw new Exception($db->getErrorMsg());
  392. }
  393. if ((int)$value == 0) {
  394. // Adjust the mapping table.
  395. // Clear the existing features settings.
  396. $db->setQuery(
  397. 'DELETE FROM #__content_frontpage' .
  398. ' WHERE content_id IN ('.implode(',', $pks).')'
  399. );
  400. if (!$db->query()) {
  401. throw new Exception($db->getErrorMsg());
  402. }
  403. } else {
  404. // first, we find out which of our new featured articles are already featured.
  405. $query = $db->getQuery(true);
  406. $query->select('f.content_id');
  407. $query->from('#__content_frontpage AS f');
  408. $query->where('content_id IN ('.implode(',', $pks).')');
  409. //echo $query;
  410. $db->setQuery($query);
  411. if (!is_array($old_featured = $db->loadColumn())) {
  412. throw new Exception($db->getErrorMsg());
  413. }
  414. // we diff the arrays to get a list of the articles that are newly featured
  415. $new_featured = array_diff($pks, $old_featured);
  416. // Featuring.
  417. $tuples = array();
  418. foreach ($new_featured as $pk) {
  419. $tuples[] = '('.$pk.', 0)';
  420. }
  421. if (count($tuples)) {
  422. $db->setQuery(
  423. 'INSERT INTO #__content_frontpage ('.$db->quoteName('content_id').', '.$db->quoteName('ordering').')' .
  424. ' VALUES '.implode(',', $tuples)
  425. );
  426. if (!$db->query()) {
  427. $this->setError($db->getErrorMsg());
  428. return false;
  429. }
  430. }
  431. }
  432. } catch (Exception $e) {
  433. $this->setError($e->getMessage());
  434. return false;
  435. }
  436. $table->reorder();
  437. $this->cleanCache();
  438. return true;
  439. }
  440. /**
  441. * A protected method to get a set of ordering conditions.
  442. *
  443. * @param object A record object.
  444. *
  445. * @return array An array of conditions to add to add to ordering queries.
  446. * @since 1.6
  447. */
  448. protected function getReorderConditions($table)
  449. {
  450. $condition = array();
  451. $condition[] = 'catid = '.(int) $table->catid;
  452. return $condition;
  453. }
  454. /**
  455. * Custom clean the cache of com_content and content modules
  456. *
  457. * @since 1.6
  458. */
  459. protected function cleanCache($group = null, $client_id = 0)
  460. {
  461. parent::cleanCache('com_content');
  462. parent::cleanCache('mod_articles_archive');
  463. parent::cleanCache('mod_articles_categories');
  464. parent::cleanCache('mod_articles_category');
  465. parent::cleanCache('mod_articles_latest');
  466. parent::cleanCache('mod_articles_news');
  467. parent::cleanCache('mod_articles_popular');
  468. }
  469. }