PageRenderTime 33ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/source/components/com_pfrepo/site/models/directories.php

https://github.com/projectfork/Projectfork
PHP | 420 lines | 252 code | 78 blank | 90 comment | 33 complexity | 8cb502b9327c733049c2bccb34829ca5 MD5 | raw file
  1. <?php
  2. /**
  3. * @package pkg_projectfork
  4. * @subpackage com_pfrepo
  5. *
  6. * @author Tobias Kuhn (eaxs)
  7. * @copyright Copyright (C) 2006-2013 Tobias Kuhn. All rights reserved.
  8. * @license http://www.gnu.org/licenses/gpl.html GNU/GPL, see LICENSE.txt
  9. */
  10. defined('_JEXEC') or die();
  11. jimport('joomla.application.component.modellist');
  12. jimport('joomla.application.component.helper');
  13. /**
  14. * This models supports retrieving lists of directory folders.
  15. *
  16. */
  17. class PFrepoModelDirectories extends JModelList
  18. {
  19. /**
  20. * Constructor.
  21. *
  22. * @param array $config An optional associative array of configuration settings.
  23. * @see jcontroller
  24. */
  25. public function __construct($config = array())
  26. {
  27. // Set field filter
  28. if (empty($config['filter_fields'])) {
  29. $config['filter_fields'] = array(
  30. 'a.id',
  31. 'a.project_id', 'project_title',
  32. 'a.title',
  33. 'a.created',
  34. 'a.created_by', 'author_name',
  35. 'a.modified',
  36. 'a.parent_id',
  37. 'a.modified_by', 'editor',
  38. 'a.checked_out',
  39. 'a.checked_out_time',
  40. 'a.access', 'access_level'
  41. );
  42. }
  43. parent::__construct($config);
  44. }
  45. /**
  46. * Get the master query for retrieving a list of items subject to the model state.
  47. *
  48. * @return jdatabasequery
  49. */
  50. public function getListQuery()
  51. {
  52. $query = $this->_db->getQuery(true);
  53. $user = JFactory::getUser();
  54. // Get possible filters
  55. $filter_project = $this->getState('filter.project');
  56. $filter_access = $this->getState('filter.access');
  57. $filter_author = $this->getState('filter.author_id');
  58. $filter_search = $this->getState('filter.search');
  59. $filter_parent = $this->getState('filter.parent_id');
  60. $filter_labels = $this->getState('filter.labels');
  61. // Select the required fields from the table.
  62. $query->select(
  63. $this->getState(
  64. 'list.select',
  65. 'a.id, a.project_id, a.title, a.alias, a.description, a.checked_out, '
  66. . 'a.checked_out_time, a.created, a.access, a.created_by, a.parent_id, '
  67. . 'a.lft, a.rgt, a.level, a.path, a.protected, a.attribs'
  68. )
  69. );
  70. $query->from('#__pf_repo_dirs AS a');
  71. // Join over the users for the checked out user.
  72. $query->select('uc.name AS editor')
  73. ->join('LEFT', '#__users AS uc ON uc.id = a.checked_out');
  74. // Join over the asset groups.
  75. $query->select('ag.title AS access_level')
  76. ->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');
  77. // Join over the users for the author.
  78. $query->select('ua.name AS author_name')
  79. ->join('LEFT', '#__users AS ua ON ua.id = a.created_by');
  80. // Join over the projects for the project title.
  81. $query->select('p.id AS project_exists, p.title AS project_title, p.alias AS project_alias')
  82. ->join('LEFT', '#__pf_projects AS p ON p.id = a.project_id');
  83. // Join over the label refs for label count
  84. $query->select('COUNT(DISTINCT lbl.id) AS label_count')
  85. ->join('LEFT', '#__pf_ref_labels AS lbl ON (lbl.item_id = a.id '
  86. . 'AND lbl.item_type = ' . $this->_db->quote('com_pfrepo.directory') . ')');
  87. // Join over the observer table for email notification status
  88. if ($user->id > 0) {
  89. $query->select('COUNT(DISTINCT obs.user_id) AS watching');
  90. $query->join('LEFT', '#__pf_ref_observer AS obs ON (obs.item_type = '
  91. . $this->_db->quote('com_pfrepo.directory') . ' AND obs.item_id = a.id AND obs.user_id = '
  92. . $this->_db->quote($user->get('id')) . ')'
  93. );
  94. }
  95. // Filter by access level.
  96. if ($filter_access) {
  97. $query->where('a.access = ' . (int) $filter_access);
  98. }
  99. // Implement View Level Access
  100. if (!$user->authorise('core.admin')) {
  101. $levels = implode(',', $user->getAuthorisedViewLevels());
  102. $query->where('a.access IN (' . $levels . ')');
  103. }
  104. // Filter by project
  105. if (is_numeric($filter_project) && $filter_project > 0) {
  106. $query->where('a.project_id = ' . (int) $filter_project);
  107. }
  108. // Filter by author
  109. if (is_numeric($filter_author)) {
  110. $type = $this->getState('filter.author_id.include', true) ? '= ' : '<>';
  111. $query->where('a.created_by ' . $type . (int) $filter_author);
  112. }
  113. // Filter by parent directory
  114. if (is_numeric($filter_parent)) {
  115. if (!empty($filter_search)) {
  116. $query2 = $this->_db->getQuery(true);
  117. $query2->select('lft, rgt')
  118. ->from('#__pf_repo_dirs')
  119. ->where('id = ' . (int) $filter_parent);
  120. $this->_db->setQuery($query2);
  121. $dir = $this->_db->loadObject();
  122. if (!empty($dir)) {
  123. $query->where('a.lft > ' . (int) $dir->lft)
  124. ->where('a.rgt < ' . (int) $dir->rgt);
  125. }
  126. }
  127. else {
  128. $query->where('a.parent_id = ' . (int) $filter_parent);
  129. }
  130. }
  131. // Filter by labels
  132. if (count($filter_labels)) {
  133. JArrayHelper::toInteger($labels);
  134. if (count($labels) > 1) {
  135. $query->where('lbl.label_id IN (' . implode(', ', $labels) . ')');
  136. }
  137. else {
  138. $query->where('lbl.label_id = ' . (int) implode(', ', $labels));
  139. }
  140. }
  141. // Filter by search in title.
  142. if (!empty($filter_search)) {
  143. if (stripos($filter_search, 'id:') === 0) {
  144. $query->where('a.id = '. (int) substr($filter_search, 3));
  145. }
  146. elseif (stripos($filter_search, 'author:') === 0) {
  147. $search = $this->_db->quote($this->_db->escape(substr($filter_search, 7), true) . '%');
  148. $query->where('(ua.name LIKE ' . $search . ' OR ua.username LIKE ' . $search . ')');
  149. }
  150. else {
  151. $search = $this->_db->quote('%' . $this->_db->escape($filter_search, true) . '%');
  152. $query->where('(a.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ')');
  153. }
  154. }
  155. // Add the list ordering clause.
  156. $order_col = $this->state->get('list.ordering', 'a.title');
  157. $order_dir = $this->state->get('list.direction', 'asc');
  158. if ($order_col != 'a.lft') {
  159. $order_col = $order_col . ' ' . $order_dir . ', a.lft';
  160. }
  161. $query->order($this->_db->escape($order_col . ' ' . $order_dir))
  162. ->group('a.id');
  163. return $query;
  164. }
  165. /**
  166. * Method to get a list of items.
  167. * Overriden to inject convert the attribs field into a JParameter object.
  168. *
  169. * @return mixed $items An array of objects on success, false on failure.
  170. */
  171. public function getItems()
  172. {
  173. $items = parent::getItems();
  174. $labels = $this->getInstance('Labels', 'PFModel');
  175. $count = (int) $this->getState('list.count_elements');
  176. if ($count) {
  177. $pks = JArrayHelper::getColumn($items, 'id');
  178. $elements = $this->getElementCount($pks);
  179. }
  180. foreach ($items as $i => &$item)
  181. {
  182. // Convert the parameter fields into objects.
  183. $params = new JRegistry;
  184. $params->loadString($item->attribs);
  185. $item->params = clone $this->getState('params');
  186. // Create slugs
  187. $item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
  188. $item->project_slug = $item->project_alias ? ($item->project_id . ':' . $item->project_alias) : $item->project_id;
  189. $item->element_count = ($count ? $elements[$item->id] : 0);
  190. $item->orphaned = empty($item->project_exists);
  191. // Get the labels
  192. if ($item->label_count > 0) {
  193. $item->labels = $labels->getConnections('com_pfrepo.directory', $item->id);
  194. }
  195. }
  196. return $items;
  197. }
  198. /**
  199. * Counts the contents of the given folders
  200. *
  201. * @param array $pks The folders to count the contents of
  202. *
  203. * @retun array $count The element count
  204. */
  205. public function getElementCount($pks)
  206. {
  207. $query = $this->_db->getQuery(true);
  208. $user = JFactory::getUser();
  209. if (!is_array($pks) || !count($pks)) return array();
  210. // Count sub-folders
  211. $query->select('parent_id, COUNT(id) AS folder_count')
  212. ->from('#__pf_repo_dirs')
  213. ->where('parent_id IN(' . implode(',', $pks) . ')');
  214. if (!$user->authorise('core.admin')) {
  215. $levels = implode(',', $user->getAuthorisedViewLevels());
  216. $query->where('access IN (' . $levels . ')');
  217. }
  218. $query->group('parent_id');
  219. $this->_db->setQuery($query);
  220. try {
  221. $folder_count = $this->_db->loadAssocList('parent_id', 'folder_count');
  222. }
  223. catch (RuntimeException $e) {
  224. $this->setError($e->getMessage());
  225. return false;
  226. }
  227. // Count notes
  228. $query->clear()
  229. ->select('dir_id, COUNT(id) AS note_count')
  230. ->from('#__pf_repo_notes')
  231. ->where('dir_id IN(' . implode(',', $pks) . ')');
  232. if (!$user->authorise('core.admin')) {
  233. $levels = implode(',', $user->getAuthorisedViewLevels());
  234. $query->where('access IN (' . $levels . ')');
  235. }
  236. $query->group('dir_id');
  237. $this->_db->setQuery($query);
  238. try {
  239. $note_count = $this->_db->loadAssocList('dir_id', 'note_count');
  240. }
  241. catch (RuntimeException $e) {
  242. $this->setError($e->getMessage());
  243. return false;
  244. }
  245. // Count files
  246. $query->clear()
  247. ->select('dir_id, COUNT(id) AS file_count')
  248. ->from('#__pf_repo_files')
  249. ->where('dir_id IN(' . implode(',', $pks) . ')');
  250. if (!$user->authorise('core.admin')) {
  251. $levels = implode(',', $user->getAuthorisedViewLevels());
  252. $query->where('access IN (' . $levels . ')');
  253. }
  254. $query->group('dir_id');
  255. $this->_db->setQuery($query);
  256. try {
  257. $file_count = $this->_db->loadAssocList('dir_id', 'file_count');
  258. }
  259. catch (RuntimeException $e) {
  260. $this->setError($e->getMessage());
  261. return false;
  262. }
  263. // Put everything together
  264. $count = array();
  265. foreach ($pks as $pk)
  266. {
  267. $count[$pk] = 0;
  268. if (isset($folder_count[$pk])) $count[$pk] += $folder_count[$pk];
  269. if (isset($note_count[$pk])) $count[$pk] += $note_count[$pk];
  270. if (isset($file_count[$pk])) $count[$pk] += $file_count[$pk];
  271. }
  272. return $count;
  273. }
  274. /**
  275. * Method to auto-populate the model state.
  276. * Note. Calling getState in this method will result in recursion.
  277. *
  278. * @return void
  279. */
  280. protected function populateState($ordering = 'a.title', $direction = 'ASC')
  281. {
  282. // Initialise variables.
  283. $app = JFactory::getApplication();
  284. $params = $app->getParams();
  285. // Adjust the context to support modal layouts.
  286. if ($layout = JRequest::getVar('layout')) $this->context .= '.' . $layout;
  287. // Set Params
  288. $this->setState('params', $params);
  289. // Config - Count elements
  290. $this->setState('list.count_elements', (int) $params->get('show_element_count'));
  291. // Filter - Search
  292. $search = JRequest::getString('filter_search', '');
  293. $this->setState('filter.search', $search);
  294. // Filter - Author
  295. $author_id = $app->getUserStateFromRequest($this->context . '.filter.author_id', 'filter_author_id');
  296. $this->setState('filter.author_id', $author_id);
  297. // Filter - Access
  298. $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '');
  299. $this->setState('filter.access', $access);
  300. // Filter - Project
  301. $project = PFApplicationHelper::getActiveProjectId('filter_project');
  302. $this->setState('filter.project', $project);
  303. // Filter - Directory
  304. $parent_id = JRequest::getUint('filter_parent_id', 1);
  305. $this->setState('filter.parent_id', $parent_id);
  306. // Filter - Labels
  307. $labels = (array) JRequest::getVar('filter_label', array(), 'post', 'array');
  308. $this->setState('filter.labels', $labels);
  309. // Do not allow to filter by author if no project is selected
  310. if ($project <= 0) {
  311. $this->setState('filter.author', '');
  312. $this->setState('filter.labels', array());
  313. $author_id = '';
  314. $labels = array();
  315. }
  316. // Filter - Is set
  317. $this->setState('filter.isset', (!empty($search) || is_numeric($author_id) || count($labels)));
  318. // Call parent method
  319. parent::populateState($ordering, $direction);
  320. }
  321. /**
  322. * Method to get a store id based on model configuration state.
  323. *
  324. * This is necessary because the model is used by the component and
  325. * different modules that might need different sets of data or different
  326. * ordering requirements.
  327. *
  328. * @param string $id A prefix for the store id.
  329. *
  330. * @return string A store id.
  331. */
  332. protected function getStoreId($id = '')
  333. {
  334. $id .= ':' . $this->getState('filter.search');
  335. $id .= ':' . $this->getState('filter.access');
  336. $id .= ':' . $this->getState('filter.author_id');
  337. $id .= ':' . $this->getState('filter.parent_id');
  338. $id .= ':' . $this->getState('filter.project');
  339. $id .= ':' . serialize($this->getState('filter.labels'));
  340. return parent::getStoreId($id);
  341. }
  342. }