PageRenderTime 78ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/core/filter_api.php

https://github.com/markkimsal/mantisbt
PHP | 4710 lines | 4192 code | 242 blank | 276 comment | 402 complexity | 8724547dee86b404c9fbc7831a69f3c1 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. # MantisBT - A PHP based bugtracking system
  3. # MantisBT is free software: you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation, either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # MantisBT is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
  15. /**
  16. * Filter API
  17. *
  18. * @package CoreAPI
  19. * @subpackage FilterAPI
  20. * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
  21. * @copyright Copyright (C) 2002 - 2010 MantisBT Team - mantisbt-dev@lists.sourceforge.net
  22. * @link http://www.mantisbt.org
  23. *
  24. * @uses access_api.php
  25. * @uses authentication_api.php
  26. * @uses bug_api.php
  27. * @uses collapse_api.php
  28. * @uses columns_api.php
  29. * @uses config_api.php
  30. * @uses constant_inc.php
  31. * @uses current_user_api.php
  32. * @uses custom_field_api.php
  33. * @uses database_api.php
  34. * @uses date_api.php
  35. * @uses error_api.php
  36. * @uses event_api.php
  37. * @uses filter_constants_inc.php
  38. * @uses gpc_api.php
  39. * @uses helper_api.php
  40. * @uses lang_api.php
  41. * @uses logging_api.php
  42. * @uses print_api.php
  43. * @uses profile_api.php
  44. * @uses project_api.php
  45. * @uses relationship_api.php
  46. * @uses string_api.php
  47. * @uses tag_api.php
  48. * @uses user_api.php
  49. * @uses utility_api.php
  50. * @uses version_api.php
  51. */
  52. require_api( 'access_api.php' );
  53. require_api( 'authentication_api.php' );
  54. require_api( 'bug_api.php' );
  55. require_api( 'collapse_api.php' );
  56. require_api( 'columns_api.php' );
  57. require_api( 'config_api.php' );
  58. require_api( 'constant_inc.php' );
  59. require_api( 'current_user_api.php' );
  60. require_api( 'custom_field_api.php' );
  61. require_api( 'database_api.php' );
  62. require_api( 'date_api.php' );
  63. require_api( 'error_api.php' );
  64. require_api( 'event_api.php' );
  65. require_api( 'filter_constants_inc.php' );
  66. require_api( 'gpc_api.php' );
  67. require_api( 'helper_api.php' );
  68. require_api( 'lang_api.php' );
  69. require_api( 'logging_api.php' );
  70. require_api( 'print_api.php' );
  71. require_api( 'profile_api.php' );
  72. require_api( 'project_api.php' );
  73. require_api( 'relationship_api.php' );
  74. require_api( 'string_api.php' );
  75. require_api( 'tag_api.php' );
  76. require_api( 'user_api.php' );
  77. require_api( 'utility_api.php' );
  78. require_api( 'version_api.php' );
  79. /**
  80. * Allow plugins to define a set of class-based filters, and register/load
  81. * them here to be used by the rest of filter_api.
  82. * @return array Mapping of field name to filter object
  83. */
  84. function filter_get_plugin_filters() {
  85. static $s_field_array = null;
  86. if ( is_null( $s_field_array ) ) {
  87. $s_field_array = array();
  88. $t_all_plugin_filters = event_signal( 'EVENT_FILTER_FIELDS' );
  89. foreach( $t_all_plugin_filters as $t_plugin => $t_plugin_filters ) {
  90. foreach( $t_plugin_filters as $t_callback => $t_plugin_filter_array ) {
  91. if ( is_array( $t_plugin_filter_array ) ) {
  92. foreach( $t_plugin_filter_array as $t_filter_class ) {
  93. if ( class_exists( $t_filter_class ) && is_subclass_of( $t_filter_class, 'MantisFilter' ) ) {
  94. $t_filter_object = new $t_filter_class();
  95. $t_field_name = $t_plugin . '_' . $t_filter_object->field;
  96. $s_field_array[ $t_field_name ] = $t_filter_object;
  97. }
  98. }
  99. }
  100. }
  101. }
  102. }
  103. return $s_field_array;
  104. }
  105. /**
  106. * Get a permalink for the current active filter. The results of using these fields by other users
  107. * can be inconsistent with the original results due to fields like "Myself", "Current Project",
  108. * and due to access level.
  109. * @param array $p_custom_filter
  110. * @return string the search.php?xxxx or an empty string if no criteria applied.
  111. */
  112. function filter_get_url( $p_custom_filter ) {
  113. $t_query = array();
  114. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PROJECT_ID] ) ) {
  115. $t_project_id = $p_custom_filter[FILTER_PROPERTY_PROJECT_ID];
  116. if( count( $t_project_id ) == 1 && $t_project_id[0] == META_FILTER_CURRENT ) {
  117. $t_project_id = array(
  118. helper_get_current_project(),
  119. );
  120. }
  121. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PROJECT_ID, $t_project_id );
  122. }
  123. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SEARCH] ) ) {
  124. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SEARCH, $p_custom_filter[FILTER_PROPERTY_SEARCH] );
  125. }
  126. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_CATEGORY_ID] ) ) {
  127. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_CATEGORY_ID, $p_custom_filter[FILTER_PROPERTY_CATEGORY_ID] );
  128. }
  129. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_REPORTER_ID] ) ) {
  130. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_REPORTER_ID, $p_custom_filter[FILTER_PROPERTY_REPORTER_ID] );
  131. }
  132. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_STATUS] ) ) {
  133. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_STATUS, $p_custom_filter[FILTER_PROPERTY_STATUS] );
  134. }
  135. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_MONITOR_USER_ID] ) ) {
  136. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_MONITOR_USER_ID, $p_custom_filter[FILTER_PROPERTY_MONITOR_USER_ID] );
  137. }
  138. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HANDLER_ID] ) ) {
  139. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HANDLER_ID, $p_custom_filter[FILTER_PROPERTY_HANDLER_ID] );
  140. }
  141. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_NOTE_USER_ID] ) ) {
  142. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_NOTE_USER_ID, $p_custom_filter[FILTER_PROPERTY_NOTE_USER_ID] );
  143. }
  144. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SEVERITY] ) ) {
  145. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SEVERITY, $p_custom_filter[FILTER_PROPERTY_SEVERITY] );
  146. }
  147. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RESOLUTION] ) ) {
  148. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RESOLUTION, $p_custom_filter[FILTER_PROPERTY_RESOLUTION] );
  149. }
  150. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PRIORITY] ) ) {
  151. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PRIORITY, $p_custom_filter[FILTER_PROPERTY_PRIORITY] );
  152. }
  153. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_VIEW_STATE] ) ) {
  154. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_VIEW_STATE, $p_custom_filter[FILTER_PROPERTY_VIEW_STATE] );
  155. }
  156. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_STICKY] ) ) {
  157. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_STICKY, $p_custom_filter[FILTER_PROPERTY_STICKY] );
  158. }
  159. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_VERSION] ) ) {
  160. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_VERSION, $p_custom_filter[FILTER_PROPERTY_VERSION] );
  161. }
  162. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_BUILD] ) ) {
  163. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_BUILD, $p_custom_filter[FILTER_PROPERTY_BUILD] );
  164. }
  165. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_FIXED_IN_VERSION] ) ) {
  166. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_FIXED_IN_VERSION, $p_custom_filter[FILTER_PROPERTY_FIXED_IN_VERSION] );
  167. }
  168. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TARGET_VERSION] ) ) {
  169. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TARGET_VERSION, $p_custom_filter[FILTER_PROPERTY_TARGET_VERSION] );
  170. }
  171. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SORT_FIELD_NAME] ) ) {
  172. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SORT_FIELD_NAME, $p_custom_filter[FILTER_PROPERTY_SORT_FIELD_NAME] );
  173. }
  174. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SORT_DIRECTION] ) ) {
  175. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SORT_DIRECTION, $p_custom_filter[FILTER_PROPERTY_SORT_DIRECTION] );
  176. }
  177. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] ) ) {
  178. if( $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] != config_get( 'default_limit_view' ) ) {
  179. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_ISSUES_PER_PAGE, $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] );
  180. }
  181. }
  182. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] ) ) {
  183. if( $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] != config_get( 'default_show_changed' ) ) {
  184. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HIGHLIGHT_CHANGED, $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] );
  185. }
  186. }
  187. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HIDE_STATUS] ) ) {
  188. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HIDE_STATUS, $p_custom_filter[FILTER_PROPERTY_HIDE_STATUS] );
  189. }
  190. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_FILTER_BY_DATE] ) ) {
  191. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_FILTER_BY_DATE, $p_custom_filter[FILTER_PROPERTY_FILTER_BY_DATE] );
  192. # The start and end dates are only applicable if filter by date is set.
  193. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_DAY] ) ) {
  194. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_START_DAY, $p_custom_filter[FILTER_PROPERTY_START_DAY] );
  195. }
  196. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_DAY] ) ) {
  197. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_END_DAY, $p_custom_filter[FILTER_PROPERTY_END_DAY] );
  198. }
  199. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_MONTH] ) ) {
  200. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_START_MONTH, $p_custom_filter[FILTER_PROPERTY_START_MONTH] );
  201. }
  202. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_MONTH] ) ) {
  203. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_END_MONTH, $p_custom_filter[FILTER_PROPERTY_END_MONTH] );
  204. }
  205. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_YEAR] ) ) {
  206. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_START_YEAR, $p_custom_filter[FILTER_PROPERTY_START_YEAR] );
  207. }
  208. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_YEAR] ) ) {
  209. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_END_YEAR, $p_custom_filter[FILTER_PROPERTY_END_YEAR] );
  210. }
  211. }
  212. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] ) ) {
  213. if( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] != -1 ) {
  214. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RELATIONSHIP_TYPE, $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] );
  215. }
  216. }
  217. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_BUG] ) ) {
  218. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RELATIONSHIP_BUG, $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_BUG] );
  219. }
  220. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PLATFORM] ) ) {
  221. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PLATFORM, $p_custom_filter[FILTER_PROPERTY_PLATFORM] );
  222. }
  223. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_OS] ) ) {
  224. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_OS, $p_custom_filter[FILTER_PROPERTY_OS] );
  225. }
  226. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_OS_BUILD] ) ) {
  227. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_OS_BUILD, $p_custom_filter[FILTER_PROPERTY_OS_BUILD] );
  228. }
  229. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TAG_STRING] ) ) {
  230. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TAG_STRING, $p_custom_filter[FILTER_PROPERTY_TAG_STRING] );
  231. }
  232. if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TAG_SELECT] ) ) {
  233. $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TAG_SELECT, $p_custom_filter[FILTER_PROPERTY_TAG_SELECT] );
  234. }
  235. if( isset( $p_custom_filter['custom_fields'] ) ) {
  236. foreach( $p_custom_filter['custom_fields'] as $t_custom_field_id => $t_custom_field_values ) {
  237. if( !filter_field_is_any( $t_custom_field_values ) ) {
  238. $t_query[] = filter_encode_field_and_value( 'custom_field_' . $t_custom_field_id, $t_custom_field_values );
  239. }
  240. }
  241. }
  242. # Allow plugins to add filter fields
  243. $t_plugin_filter_array = filter_get_plugin_filters();
  244. foreach( $t_plugin_filter_array as $t_field_name => $t_filter_object ) {
  245. if( !filter_field_is_any( $p_custom_filter[ $t_field_name ] ) ) {
  246. $t_query[] = filter_encode_field_and_value( $t_field_name, $p_custom_filter[ $t_field_name ], $t_filter_object->type );
  247. }
  248. }
  249. if( count( $t_query ) > 0 ) {
  250. $t_query_str = implode( $t_query, '&' );
  251. $t_url = config_get( 'path' ) . 'search.php?' . $t_query_str;
  252. } else {
  253. $t_url = '';
  254. }
  255. return $t_url;
  256. }
  257. /**
  258. * Encodes a field and it's value for the filter URL. This handles the URL encoding
  259. * and arrays.
  260. * @param string $p_field_name The field name.
  261. * @param string $p_field_value The field value (can be an array)
  262. * @return string url encoded string
  263. */
  264. function filter_encode_field_and_value( $p_field_name, $p_field_value, $p_field_type=null ) {
  265. $t_query_array = array();
  266. if( is_array( $p_field_value ) ) {
  267. $t_count = count( $p_field_value );
  268. if( $t_count > 1 || $p_field_type == FILTER_TYPE_MULTI_STRING || $p_field_type == FILTER_TYPE_MULTI_INT ) {
  269. foreach( $p_field_value as $t_value ) {
  270. $t_query_array[] = urlencode( $p_field_name . '[]' ) . '=' . urlencode( $t_value );
  271. }
  272. }
  273. else if( $t_count == 1 ) {
  274. $t_query_array[] = urlencode( $p_field_name ) . '=' . urlencode( $p_field_value[0] );
  275. }
  276. } else {
  277. $t_query_array[] = urlencode( $p_field_name ) . '=' . urlencode( $p_field_value );
  278. }
  279. return implode( $t_query_array, '&' );
  280. }
  281. # ==========================================================================
  282. # GENERAL FUNCTIONS =
  283. # ==========================================================================
  284. /**
  285. * Checks the supplied value to see if it is an ANY value.
  286. * @param string $p_field_value - The value to check.
  287. * @return bool true for "ANY" values and false for others. "ANY" means filter criteria not active.
  288. */
  289. function filter_field_is_any( $p_field_value ) {
  290. if( is_array( $p_field_value ) ) {
  291. if( count( $p_field_value ) == 0 ) {
  292. return true;
  293. }
  294. foreach( $p_field_value as $t_value ) {
  295. if(( META_FILTER_ANY == $t_value ) && ( is_numeric( $t_value ) ) ) {
  296. return true;
  297. }
  298. }
  299. } else {
  300. if( is_string( $p_field_value ) && is_blank( $p_field_value ) ) {
  301. return true;
  302. }
  303. if( is_bool( $p_field_value ) && !$p_field_value ) {
  304. return true;
  305. }
  306. if(( META_FILTER_ANY == $p_field_value ) && ( is_numeric( $p_field_value ) ) ) {
  307. return true;
  308. }
  309. }
  310. return false;
  311. }
  312. /**
  313. * Checks the supplied value to see if it is a NONE value.
  314. * @param string $p_field_value - The value to check.
  315. * @return bool true for "NONE" values and false for others.
  316. * @todo is a check for these necessary? if ( ( $t_filter_value === 'none' ) || ( $t_filter_value === '[none]' ) )
  317. */
  318. function filter_field_is_none( $p_field_value ) {
  319. if( is_array( $p_field_value ) ) {
  320. foreach( $p_field_value as $t_value ) {
  321. if(( META_FILTER_NONE == $t_value ) && ( is_numeric( $t_value ) ) ) {
  322. return true;
  323. }
  324. }
  325. } else {
  326. if( is_string( $p_field_value ) && is_blank( $p_field_value ) ) {
  327. return false;
  328. }
  329. if(( META_FILTER_NONE == $p_field_value ) && ( is_numeric( $p_field_value ) ) ) {
  330. return true;
  331. }
  332. }
  333. return false;
  334. }
  335. /**
  336. * Checks the supplied value to see if it is a MYSELF value.
  337. * @param string $p_field_value - The value to check.
  338. * @return bool true for "MYSELF" values and false for others.
  339. */
  340. function filter_field_is_myself( $p_field_value ) {
  341. return( META_FILTER_MYSELF == $p_field_value ? TRUE : FALSE );
  342. }
  343. /**
  344. * @param $p_count
  345. * @param $p_per_page
  346. * @return int
  347. */
  348. function filter_per_page( $p_filter, $p_count, $p_per_page ) {
  349. $p_per_page = (( NULL == $p_per_page ) ? (int) $p_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] : $p_per_page );
  350. $p_per_page = (( 0 == $p_per_page || -1 == $p_per_page ) ? $p_count : $p_per_page );
  351. return (int) abs( $p_per_page );
  352. }
  353. /**
  354. * Use $p_count and $p_per_page to determine how many pages to split this list up into.
  355. * For the sake of consistency have at least one page, even if it is empty.
  356. * @param $p_count
  357. * @param $p_per_page
  358. * @return $t_page_count
  359. */
  360. function filter_page_count( $p_count, $p_per_page ) {
  361. $t_page_count = ceil( $p_count / $p_per_page );
  362. if( $t_page_count < 1 ) {
  363. $t_page_count = 1;
  364. }
  365. return $t_page_count;
  366. }
  367. /**
  368. * Checks to make sure $p_page_number isn't past the last page.
  369. * and that $p_page_number isn't before the first page
  370. * @param $p_page_number
  371. * @param $p_page_count
  372. */
  373. function filter_valid_page_number( $p_page_number, $p_page_count ) {
  374. if( $p_page_number > $p_page_count ) {
  375. $p_page_number = $p_page_count;
  376. }
  377. if( $p_page_number < 1 ) {
  378. $p_page_number = 1;
  379. }
  380. return $p_page_number;
  381. }
  382. /**
  383. * Figure out the offset into the db query, offset is which record to start querying from
  384. * @param int $p_page_number
  385. * @param int $p_per_page
  386. * @return int
  387. */
  388. function filter_offset( $p_page_number, $p_per_page ) {
  389. return(( (int) $p_page_number -1 ) * (int) $p_per_page );
  390. }
  391. /**
  392. * Make sure that our filters are entirely correct and complete (it is possible that they are not).
  393. * We need to do this to cover cases where we don't have complete control over the filters given.s
  394. * @param array $p_filter_arr
  395. * @return mixed
  396. * @todo function needs to be abstracted
  397. */
  398. function filter_ensure_valid_filter( $p_filter_arr ) {
  399. # extend current filter to add information passed via POST
  400. if( !isset( $p_filter_arr['_version'] ) ) {
  401. $p_filter_arr['_version'] = config_get( 'cookie_version' );
  402. }
  403. $t_cookie_vers = (int) utf8_substr( $p_filter_arr['_version'], 1 );
  404. if( utf8_substr( config_get( 'cookie_version' ), 1 ) > $t_cookie_vers ) {
  405. # if the version is old, update it
  406. $p_filter_arr['_version'] = config_get( 'cookie_version' );
  407. }
  408. if( !isset( $p_filter_arr['_view_type'] ) ) {
  409. $p_filter_arr['_view_type'] = gpc_get_string( 'view_type', 'simple' );
  410. }
  411. if( !isset( $p_filter_arr[FILTER_PROPERTY_ISSUES_PER_PAGE] ) ) {
  412. $p_filter_arr[FILTER_PROPERTY_ISSUES_PER_PAGE] = gpc_get_int( FILTER_PROPERTY_ISSUES_PER_PAGE, config_get( 'default_limit_view' ) );
  413. }
  414. if( !isset( $p_filter_arr[FILTER_PROPERTY_HIGHLIGHT_CHANGED] ) ) {
  415. $p_filter_arr[FILTER_PROPERTY_HIGHLIGHT_CHANGED] = config_get( 'default_show_changed' );
  416. }
  417. if( !isset( $p_filter_arr[FILTER_PROPERTY_STICKY] ) ) {
  418. $p_filter_arr[FILTER_PROPERTY_STICKY] = gpc_string_to_bool( config_get( 'show_sticky_issues' ) );
  419. }
  420. if( !isset( $p_filter_arr[FILTER_PROPERTY_SORT_FIELD_NAME] ) ) {
  421. $p_filter_arr[FILTER_PROPERTY_SORT_FIELD_NAME] = "last_updated";
  422. }
  423. if( !isset( $p_filter_arr[FILTER_PROPERTY_SORT_DIRECTION] ) ) {
  424. $p_filter_arr[FILTER_PROPERTY_SORT_DIRECTION] = "DESC";
  425. }
  426. if( !isset( $p_filter_arr[FILTER_PROPERTY_PLATFORM] ) ) {
  427. $p_filter_arr[FILTER_PROPERTY_PLATFORM] = array(
  428. 0 => META_FILTER_ANY,
  429. );
  430. }
  431. if( !isset( $p_filter_arr[FILTER_PROPERTY_OS] ) ) {
  432. $p_filter_arr[FILTER_PROPERTY_OS] = array(
  433. 0 => META_FILTER_ANY,
  434. );
  435. }
  436. if( !isset( $p_filter_arr[FILTER_PROPERTY_OS_BUILD] ) ) {
  437. $p_filter_arr[FILTER_PROPERTY_OS_BUILD] = array(
  438. 0 => META_FILTER_ANY,
  439. );
  440. }
  441. if( !isset( $p_filter_arr[FILTER_PROPERTY_PROJECT_ID] ) ) {
  442. $p_filter_arr[FILTER_PROPERTY_PROJECT_ID] = array(
  443. 0 => META_FILTER_CURRENT,
  444. );
  445. }
  446. if( !isset( $p_filter_arr[FILTER_PROPERTY_START_MONTH] ) ) {
  447. $p_filter_arr[FILTER_PROPERTY_START_MONTH] = gpc_get_string( FILTER_PROPERTY_START_MONTH, date( 'm' ) );
  448. }
  449. if( !isset( $p_filter_arr[FILTER_PROPERTY_START_DAY] ) ) {
  450. $p_filter_arr[FILTER_PROPERTY_START_DAY] = gpc_get_string( FILTER_PROPERTY_START_DAY, 1 );
  451. }
  452. if( !isset( $p_filter_arr[FILTER_PROPERTY_START_YEAR] ) ) {
  453. $p_filter_arr[FILTER_PROPERTY_START_YEAR] = gpc_get_string( FILTER_PROPERTY_START_YEAR, date( 'Y' ) );
  454. }
  455. if( !isset( $p_filter_arr[FILTER_PROPERTY_END_MONTH] ) ) {
  456. $p_filter_arr[FILTER_PROPERTY_END_MONTH] = gpc_get_string( FILTER_PROPERTY_END_MONTH, date( 'm' ) );
  457. }
  458. if( !isset( $p_filter_arr[FILTER_PROPERTY_END_DAY] ) ) {
  459. $p_filter_arr[FILTER_PROPERTY_END_DAY] = gpc_get_string( FILTER_PROPERTY_END_DAY, date( 'd' ) );
  460. }
  461. if( !isset( $p_filter_arr[FILTER_PROPERTY_END_YEAR] ) ) {
  462. $p_filter_arr[FILTER_PROPERTY_END_YEAR] = gpc_get_string( FILTER_PROPERTY_END_YEAR, date( 'Y' ) );
  463. }
  464. if( !isset( $p_filter_arr[FILTER_PROPERTY_SEARCH] ) ) {
  465. $p_filter_arr[FILTER_PROPERTY_SEARCH] = '';
  466. }
  467. if( !isset( $p_filter_arr[FILTER_PROPERTY_FILTER_BY_DATE] ) ) {
  468. $p_filter_arr[FILTER_PROPERTY_FILTER_BY_DATE] = gpc_get_bool( FILTER_PROPERTY_FILTER_BY_DATE, false );
  469. }
  470. if( !isset( $p_filter_arr[FILTER_PROPERTY_VIEW_STATE] ) ) {
  471. $p_filter_arr[FILTER_PROPERTY_VIEW_STATE] = gpc_get( FILTER_PROPERTY_VIEW_STATE, '' );
  472. }
  473. else if( filter_field_is_any( $p_filter_arr[FILTER_PROPERTY_VIEW_STATE] ) ) {
  474. $p_filter_arr[FILTER_PROPERTY_VIEW_STATE] = META_FILTER_ANY;
  475. }
  476. if( !isset( $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_TYPE] ) ) {
  477. $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_TYPE] = gpc_get_int( FILTER_PROPERTY_RELATIONSHIP_TYPE, -1 );
  478. }
  479. if( !isset( $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_BUG] ) ) {
  480. $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_BUG] = gpc_get_int( FILTER_PROPERTY_RELATIONSHIP_BUG, 0 );
  481. }
  482. if( !isset( $p_filter_arr[FILTER_PROPERTY_TARGET_VERSION] ) ) {
  483. $p_filter_arr[FILTER_PROPERTY_TARGET_VERSION] = META_FILTER_ANY;
  484. }
  485. if( !isset( $p_filter_arr[FILTER_PROPERTY_TAG_STRING] ) ) {
  486. $p_filter_arr[FILTER_PROPERTY_TAG_STRING] = gpc_get_string( FILTER_PROPERTY_TAG_STRING, '' );
  487. }
  488. if( !isset( $p_filter_arr[FILTER_PROPERTY_TAG_SELECT] ) ) {
  489. $p_filter_arr[FILTER_PROPERTY_TAG_SELECT] = gpc_get_string( FILTER_PROPERTY_TAG_SELECT, '' );
  490. }
  491. # initialize plugin filters
  492. $t_plugin_filters = filter_get_plugin_filters();
  493. foreach( $t_plugin_filters as $t_field_name => $t_filter_object ) {
  494. if( !isset( $p_filter_arr[ $t_field_name ] ) ) {
  495. switch( $t_filter_object->type ) {
  496. case FILTER_TYPE_STRING:
  497. $p_filter_arr[ $t_field_name ] = gpc_get_string( $t_field_name, $t_filter_object->default );
  498. break;
  499. case FILTER_TYPE_INT:
  500. $p_filter_arr[ $t_field_name ] = gpc_get_int( $t_field_name, (int)$t_filter_object->default );
  501. break;
  502. case FILTER_TYPE_BOOLEAN:
  503. $p_filter_arr[ $t_field_name ] = gpc_get_bool( $t_field_name, (bool)$t_filter_object->default );
  504. break;
  505. case FILTER_TYPE_MULTI_STRING:
  506. $p_filter_arr[ $t_field_name ] = gpc_get_string_array( $t_field_name, array( 0 => META_FILTER_ANY ) );
  507. break;
  508. case FILTER_TYPE_MULTI_INT:
  509. $p_filter_arr[ $t_field_name ] = gpc_get_int_array( $t_field_name, array( 0 => META_FILTER_ANY ) );
  510. break;
  511. default:
  512. $p_filter_arr[ $t_field_name ] = META_FILTER_ANY;
  513. }
  514. }
  515. if ( ! $t_filter_object->validate( $p_filter_arr[ $t_field_name ] ) ) {
  516. $p_filter_arr[ $t_field_name ] = $t_filter_object->default;
  517. }
  518. }
  519. $t_custom_fields = custom_field_get_ids();
  520. # @@@ (thraxisp) This should really be the linked ids, but we don't know the project
  521. $f_custom_fields_data = array();
  522. if( is_array( $t_custom_fields ) && ( count( $t_custom_fields ) > 0 ) ) {
  523. foreach( $t_custom_fields as $t_cfid ) {
  524. if( is_array( gpc_get( 'custom_field_' . $t_cfid, null ) ) ) {
  525. $f_custom_fields_data[$t_cfid] = gpc_get_string_array( 'custom_field_' . $t_cfid, META_FILTER_ANY );
  526. } else {
  527. $f_custom_fields_data[$t_cfid] = gpc_get_string( 'custom_field_' . $t_cfid, META_FILTER_ANY );
  528. $f_custom_fields_data[$t_cfid] = array(
  529. $f_custom_fields_data[$t_cfid],
  530. );
  531. }
  532. }
  533. }
  534. # validate sorting
  535. $t_fields = helper_get_columns_to_view();
  536. $t_n_fields = count( $t_fields );
  537. for( $i = 0;$i < $t_n_fields;$i++ ) {
  538. if( isset( $t_fields[$i] ) && in_array( $t_fields[$i], array( 'selection', 'edit', 'bugnotes_count', 'attachment' ) ) ) {
  539. unset( $t_fields[$i] );
  540. }
  541. }
  542. $t_sort_fields = explode( ',', $p_filter_arr['sort'] );
  543. $t_dir_fields = explode( ',', $p_filter_arr['dir'] );
  544. for( $i = 0;$i < 2;$i++ ) {
  545. if( isset( $t_sort_fields[$i] ) ) {
  546. $t_drop = false;
  547. $t_sort = $t_sort_fields[$i];
  548. if( strpos( $t_sort, 'custom_' ) === 0 ) {
  549. if( false === custom_field_get_id_from_name( utf8_substr( $t_sort, utf8_strlen( 'custom_' ) ) ) ) {
  550. $t_drop = true;
  551. }
  552. } else {
  553. if( !in_array( $t_sort, $t_fields ) ) {
  554. $t_drop = true;
  555. }
  556. }
  557. if( !in_array( $t_dir_fields[$i], array( "ASC", "DESC" ) ) ) {
  558. $t_drop = true;
  559. }
  560. if( $t_drop ) {
  561. unset( $t_sort_fields[$i] );
  562. unset( $t_dir_fields[$i] );
  563. }
  564. }
  565. }
  566. if( count( $t_sort_fields ) > 0 ) {
  567. $p_filter_arr['sort'] = implode( ',', $t_sort_fields );
  568. $p_filter_arr['dir'] = implode( ',', $t_dir_fields );
  569. } else {
  570. $p_filter_arr['sort'] = "last_updated";
  571. $p_filter_arr['dir'] = "DESC";
  572. }
  573. # validate or filter junk from other fields
  574. $t_multi_select_list = array(
  575. FILTER_PROPERTY_CATEGORY_ID => 'string',
  576. FILTER_PROPERTY_SEVERITY => 'int',
  577. FILTER_PROPERTY_STATUS => 'int',
  578. FILTER_PROPERTY_REPORTER_ID => 'int',
  579. FILTER_PROPERTY_HANDLER_ID => 'int',
  580. FILTER_PROPERTY_NOTE_USER_ID => 'int',
  581. FILTER_PROPERTY_RESOLUTION => 'int',
  582. FILTER_PROPERTY_PRIORITY => 'int',
  583. FILTER_PROPERTY_BUILD => 'string',
  584. FILTER_PROPERTY_VERSION => 'string',
  585. FILTER_PROPERTY_HIDE_STATUS => 'int',
  586. FILTER_PROPERTY_FIXED_IN_VERSION => 'string',
  587. FILTER_PROPERTY_TARGET_VERSION => 'string',
  588. FILTER_PROPERTY_MONITOR_USER_ID => 'int',
  589. FILTER_PROPERTY_PROFILE_ID => 'int',
  590. );
  591. foreach( $t_multi_select_list as $t_multi_field_name => $t_multi_field_type ) {
  592. if( !isset( $p_filter_arr[$t_multi_field_name] ) ) {
  593. if( FILTER_PROPERTY_HIDE_STATUS == $t_multi_field_name ) {
  594. $p_filter_arr[$t_multi_field_name] = array(
  595. config_get( 'hide_status_default' ),
  596. );
  597. }
  598. else if( 'custom_fields' == $t_multi_field_name ) {
  599. $p_filter_arr[$t_multi_field_name] = array(
  600. $f_custom_fields_data,
  601. );
  602. } else {
  603. $p_filter_arr[$t_multi_field_name] = array(
  604. META_FILTER_ANY,
  605. );
  606. }
  607. } else {
  608. if( !is_array( $p_filter_arr[$t_multi_field_name] ) ) {
  609. $p_filter_arr[$t_multi_field_name] = array(
  610. $p_filter_arr[$t_multi_field_name],
  611. );
  612. }
  613. $t_checked_array = array();
  614. foreach( $p_filter_arr[$t_multi_field_name] as $t_filter_value ) {
  615. $t_filter_value = stripslashes( $t_filter_value );
  616. if(( $t_filter_value === 'any' ) || ( $t_filter_value === '[any]' ) ) {
  617. $t_filter_value = META_FILTER_ANY;
  618. }
  619. if(( $t_filter_value === 'none' ) || ( $t_filter_value === '[none]' ) ) {
  620. $t_filter_value = META_FILTER_NONE;
  621. }
  622. if( 'string' == $t_multi_field_type ) {
  623. $t_checked_array[] = db_prepare_string( $t_filter_value );
  624. }
  625. else if( 'int' == $t_multi_field_type ) {
  626. $t_checked_array[] = db_prepare_int( $t_filter_value );
  627. }
  628. else if( 'array' == $t_multi_field_type ) {
  629. $t_checked_array[] = $t_filter_value;
  630. }
  631. }
  632. $p_filter_arr[$t_multi_field_name] = $t_checked_array;
  633. }
  634. }
  635. if( is_array( $t_custom_fields ) && ( count( $t_custom_fields ) > 0 ) ) {
  636. foreach( $t_custom_fields as $t_cfid ) {
  637. if( !isset( $p_filter_arr['custom_fields'][$t_cfid] ) ) {
  638. $p_filter_arr['custom_fields'][$t_cfid] = array(
  639. META_FILTER_ANY,
  640. );
  641. } else {
  642. if( !is_array( $p_filter_arr['custom_fields'][$t_cfid] ) ) {
  643. $p_filter_arr['custom_fields'][$t_cfid] = array(
  644. $p_filter_arr['custom_fields'][$t_cfid],
  645. );
  646. }
  647. $t_checked_array = array();
  648. foreach( $p_filter_arr['custom_fields'][$t_cfid] as $t_filter_value ) {
  649. $t_filter_value = stripslashes( $t_filter_value );
  650. if(( $t_filter_value === 'any' ) || ( $t_filter_value === '[any]' ) ) {
  651. $t_filter_value = META_FILTER_ANY;
  652. }
  653. $t_checked_array[] = db_prepare_string( $t_filter_value );
  654. }
  655. $p_filter_arr['custom_fields'][$t_cfid] = $t_checked_array;
  656. }
  657. }
  658. }
  659. # all of our filter values are now guaranteed to be there, and correct.
  660. return $p_filter_arr;
  661. }
  662. /**
  663. * Get the standard filter that is to be used when no filter was previously saved.
  664. * When creating specific filters, this can be used as a basis for the filter, where
  665. * specific entries can be overridden.
  666. * @return mixed
  667. */
  668. function filter_get_default() {
  669. $t_hide_status_default = config_get( 'hide_status_default' );
  670. $t_default_show_changed = config_get( 'default_show_changed' );
  671. $t_filter = array(
  672. FILTER_PROPERTY_CATEGORY_ID => Array(
  673. '0' => META_FILTER_ANY,
  674. ),
  675. FILTER_PROPERTY_SEVERITY => Array(
  676. '0' => META_FILTER_ANY,
  677. ),
  678. FILTER_PROPERTY_STATUS => Array(
  679. '0' => META_FILTER_ANY,
  680. ),
  681. FILTER_PROPERTY_HIGHLIGHT_CHANGED => $t_default_show_changed,
  682. FILTER_PROPERTY_REPORTER_ID => Array(
  683. '0' => META_FILTER_ANY,
  684. ),
  685. FILTER_PROPERTY_HANDLER_ID => Array(
  686. '0' => META_FILTER_ANY,
  687. ),
  688. FILTER_PROPERTY_PROJECT_ID => Array(
  689. '0' => META_FILTER_CURRENT,
  690. ),
  691. FILTER_PROPERTY_RESOLUTION => Array(
  692. '0' => META_FILTER_ANY,
  693. ),
  694. FILTER_PROPERTY_BUILD => Array(
  695. '0' => META_FILTER_ANY,
  696. ),
  697. FILTER_PROPERTY_VERSION => Array(
  698. '0' => META_FILTER_ANY,
  699. ),
  700. FILTER_PROPERTY_HIDE_STATUS => Array(
  701. '0' => $t_hide_status_default,
  702. ),
  703. FILTER_PROPERTY_MONITOR_USER_ID => Array(
  704. '0' => META_FILTER_ANY,
  705. ),
  706. FILTER_PROPERTY_SORT_FIELD_NAME => 'last_updated',
  707. FILTER_PROPERTY_SORT_DIRECTION => 'DESC',
  708. FILTER_PROPERTY_ISSUES_PER_PAGE => config_get( 'default_limit_view' ),
  709. );
  710. return filter_ensure_valid_filter( $t_filter );
  711. }
  712. /**
  713. * Deserialize filter string
  714. * @param string $p_serialized_filter
  715. * @return mixed $t_filter array
  716. * @see filter_ensure_valid_filter
  717. */
  718. function filter_deserialize( $p_serialized_filter ) {
  719. if( is_blank( $p_serialized_filter ) ) {
  720. return false;
  721. }
  722. # check to see if new cookie is needed
  723. $t_setting_arr = explode( '#', $p_serialized_filter, 2 );
  724. if(( $t_setting_arr[0] == 'v1' ) || ( $t_setting_arr[0] == 'v2' ) || ( $t_setting_arr[0] == 'v3' ) || ( $t_setting_arr[0] == 'v4' ) ) {
  725. # these versions can't be salvaged, they are too old to update
  726. return false;
  727. }
  728. # We shouldn't need to do this anymore, as filters from v5 onwards should cope with changing
  729. # filter indices dynamically
  730. $t_filter_array = array();
  731. if( isset( $t_setting_arr[1] ) ) {
  732. $t_filter_array = unserialize( $t_setting_arr[1] );
  733. } else {
  734. return false;
  735. }
  736. if( $t_filter_array['_version'] != config_get( 'cookie_version' ) ) {
  737. # if the version is not new enough, update it using defaults
  738. return filter_ensure_valid_filter( $t_filter_array );
  739. }
  740. return $t_filter_array;
  741. }
  742. /**
  743. * Check if the filter cookie exists and is of the correct version.
  744. * @return bool
  745. */
  746. function filter_is_cookie_valid() {
  747. $t_view_all_cookie_id = gpc_get_cookie( config_get( 'view_all_cookie' ), '' );
  748. $t_view_all_cookie = filter_db_get_filter( $t_view_all_cookie_id );
  749. # check to see if the cookie does not exist
  750. if( is_blank( $t_view_all_cookie ) ) {
  751. return false;
  752. }
  753. # check to see if new cookie is needed
  754. $t_setting_arr = explode( '#', $t_view_all_cookie, 2 );
  755. if(( $t_setting_arr[0] == 'v1' ) || ( $t_setting_arr[0] == 'v2' ) || ( $t_setting_arr[0] == 'v3' ) || ( $t_setting_arr[0] == 'v4' ) ) {
  756. return false;
  757. }
  758. # We shouldn't need to do this anymore, as filters from v5 onwards should cope with changing
  759. # filter indices dynamically
  760. $t_filter_cookie_arr = array();
  761. if( isset( $t_setting_arr[1] ) ) {
  762. $t_filter_cookie_arr = unserialize( $t_setting_arr[1] );
  763. } else {
  764. return false;
  765. }
  766. if( $t_filter_cookie_arr['_version'] != config_get( 'cookie_version' ) ) {
  767. return false;
  768. }
  769. return true;
  770. }
  771. /**
  772. * Get the array fields specified by $p_filter_id
  773. * using the cached row if it's available
  774. * @param int $p_filter_id
  775. * @return mixed a filter row
  776. */
  777. function filter_get_row( $p_filter_id ) {
  778. return filter_cache_row( $p_filter_id );
  779. }
  780. /**
  781. * Get the value of the filter field specified by filter id and field name
  782. * @param int $p_filter_id
  783. * @param string $p_field_name
  784. * @return string
  785. */
  786. function filter_get_field( $p_filter_id, $p_field_name ) {
  787. $row = filter_get_row( $p_filter_id );
  788. if( isset( $row[$p_field_name] ) ) {
  789. return $row[$p_field_name];
  790. } else {
  791. error_parameters( $p_field_name );
  792. trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
  793. return '';
  794. }
  795. }
  796. /**
  797. * Add sort parameters to the query clauses
  798. * @param array $p_filter
  799. * @param bool $p_show_sticky
  800. * @param array $p_query_clauses
  801. * @return array $p_query_clauses
  802. */
  803. function filter_get_query_sort_data( &$p_filter, $p_show_sticky, $p_query_clauses ) {
  804. $t_bug_table = db_get_table( 'bug' );
  805. $t_custom_field_string_table = db_get_table( 'custom_field_string' );
  806. # if sort is blank then default the sort and direction. This is to fix the
  807. # symptoms of #3953. Note that even if the main problem is fixed, we may
  808. # have to keep this code for a while to handle filters saved with this blank field.
  809. if( is_blank( $p_filter[FILTER_PROPERTY_SORT_FIELD_NAME] ) ) {
  810. $p_filter[FILTER_PROPERTY_SORT_FIELD_NAME] = 'last_updated';
  811. $p_filter[FILTER_PROPERTY_SORT_DIRECTION] = 'DESC';
  812. }
  813. $p_query_clauses['order'] = array();
  814. $t_sort_fields = explode( ',', $p_filter[FILTER_PROPERTY_SORT_FIELD_NAME] );
  815. $t_dir_fields = explode( ',', $p_filter[FILTER_PROPERTY_SORT_DIRECTION] );
  816. $t_plugin_columns = columns_get_plugin_columns();
  817. if ( gpc_string_to_bool( $p_filter[FILTER_PROPERTY_STICKY] ) && ( NULL !== $p_show_sticky ) ) {
  818. $p_query_clauses['order'][] = "$t_bug_table.sticky DESC";
  819. }
  820. $t_count = count( $t_sort_fields );
  821. for( $i = 0;$i < $t_count;$i++ ) {
  822. $c_sort = db_prepare_string( $t_sort_fields[$i] );
  823. $c_dir = 'DESC' == $t_dir_fields[$i] ? 'DESC' : 'ASC';
  824. if( !in_array( $t_sort_fields[$i], array_slice( $t_sort_fields, $i + 1 ) ) ) {
  825. # if sorting by a custom field
  826. if( strpos( $c_sort, 'custom_' ) === 0 ) {
  827. $t_custom_field = utf8_substr( $c_sort, utf8_strlen( 'custom_' ) );
  828. $t_custom_field_id = custom_field_get_id_from_name( $t_custom_field );
  829. $c_cf_alias = str_replace( ' ', '_', $t_custom_field );
  830. $t_cf_table_alias = $t_custom_field_string_table . '_' . $t_custom_field_id;
  831. $t_cf_select = "$t_cf_table_alias.value $c_cf_alias";
  832. # check to be sure this field wasn't already added to the query.
  833. if( !in_array( $t_cf_select, $p_query_clauses['select'] ) ) {
  834. $p_query_clauses['select'][] = $t_cf_select;
  835. $p_query_clauses['join'][] = "LEFT JOIN $t_custom_field_string_table $t_cf_table_alias ON $t_bug_table.id = $t_cf_table_alias.bug_id AND $t_cf_table_alias.field_id = $t_custom_field_id";
  836. }
  837. $p_query_clauses['order'][] = "$c_cf_alias $c_dir";
  838. # if sorting by plugin columns
  839. } else if ( isset( $t_plugin_columns[ $t_sort_fields[$i] ] ) ) {
  840. $t_column_object = $t_plugin_columns[ $t_sort_fields[$i] ];
  841. if ( $t_column_object->sortable ) {
  842. $t_clauses = $t_column_object->sortquery( $c_dir );
  843. if ( is_array( $t_clauses ) ) {
  844. if ( isset( $t_clauses['join'] ) ) {
  845. $p_query_clauses['join'][] = $t_clauses['join'];
  846. }
  847. if ( isset( $t_clauses['order'] ) ) {
  848. $p_query_clauses['order'][] = $t_clauses['order'];
  849. }
  850. }
  851. }
  852. # standard column
  853. } else {
  854. if ( 'last_updated' == $c_sort ) {
  855. $c_sort = "last_updated";
  856. }
  857. $p_query_clauses['order'][] = "$t_bug_table.$c_sort $c_dir";
  858. }
  859. }
  860. }
  861. # add basic sorting if necessary
  862. if( !in_array( 'last_updated', $t_sort_fields ) ) {
  863. $p_query_clauses['order'][] = "$t_bug_table.last_updated DESC";
  864. }
  865. if( !in_array( 'date_submitted', $t_sort_fields ) ) {
  866. $p_query_clauses['order'][] = "$t_bug_table.date_submitted DESC";
  867. }
  868. return $p_query_clauses;
  869. }
  870. /**
  871. * Remove any duplicate values in certain elements of query_clauses
  872. * Do not loop over query clauses as some keys may contain valid duplicate values.
  873. * We basically want unique values for just the base query elements select, from, and join
  874. * 'where' and 'where_values' key should not have duplicates as that is handled earlier and applying
  875. * array_unique here could cause problems with the query.
  876. * @param $p_query_clauses
  877. * @return $p_query_clauses
  878. */
  879. function filter_unique_query_clauses( $p_query_clauses ) {
  880. $p_query_clauses['select'] = array_unique( $p_query_clauses['select'] );
  881. $p_query_clauses['from'] = array_unique( $p_query_clauses['from'] );
  882. $p_query_clauses['join'] = array_unique( $p_query_clauses['join'] );
  883. return $p_query_clauses;
  884. }
  885. /**
  886. * Build a query with the query clauses array, query for bug count and return the result
  887. * @param array $p_query_clauses
  888. * @return int
  889. */
  890. function filter_get_bug_count( $p_query_clauses ) {
  891. $t_bug_table = db_get_table( 'bug' );
  892. $p_query_clauses = filter_unique_query_clauses( $p_query_clauses );
  893. $t_select_string = "SELECT Count( DISTINCT $t_bug_table.id ) as idcnt ";
  894. $t_from_string = " FROM " . implode( ', ', $p_query_clauses['from'] );
  895. $t_join_string = (( count( $p_query_clauses['join'] ) > 0 ) ? implode( ' ', $p_query_clauses['join'] ) : '' );
  896. $t_where_string = (( count( $p_query_clauses['where'] ) > 0 ) ? 'WHERE ' . implode( ' AND ', $p_query_clauses['where'] ) : '' );
  897. $t_result = db_query_bound( "$t_select_string $t_from_string $t_join_string $t_where_string", $p_query_clauses['where_values'] );
  898. return db_result( $t_result );
  899. }
  900. /**
  901. * @todo Had to make all these parameters required because we can't use
  902. * call-time pass by reference anymore. I really preferred not having
  903. * to pass all the params in if you didn't want to, but I wanted to get
  904. * rid of the errors for now. If we can think of a better way later
  905. * (maybe return an object) that would be great.
  906. *
  907. * @param int $p_page_number the page you want to see (set to the actual page on return)
  908. * @param int $p_per_page the number of bugs to see per page (set to actual on return)
  909. * -1 indicates you want to see all bugs
  910. * null indicates you want to use the value specified in the filter
  911. * @param int $p_page_count you don't need to give a value here, the number of pages will be stored here on return
  912. * @param int $p_bug_count you don't need to give a value here, the number of bugs will be stored here on return
  913. * @param mixed $p_custom_filter Filter to use.
  914. * @param int $p_project_id project id to use in filtering.
  915. * @param int $p_user_id user id to use as current user when filtering.
  916. * @param bool $p_show_sticky get sticky issues only.
  917. */
  918. function filter_get_bug_rows( &$p_page_number, &$p_per_page, &$p_page_count, &$p_bug_count, $p_custom_filter = null, $p_project_id = null, $p_user_id = null, $p_show_sticky = null ) {
  919. log_event( LOG_FILTERING, 'START NEW FILTER QUERY' );
  920. $t_bug_table = db_get_table( 'bug' );
  921. $t_bug_text_table = db_get_table( 'bug_text' );
  922. $t_bugnote_table = db_get_table( 'bugnote' );
  923. $t_category_table = db_get_table( 'category' );
  924. $t_custom_field_string_table = db_get_table( 'custom_field_string' );
  925. $t_bugnote_text_table = db_get_table( 'bugnote_text' );
  926. $t_project_table = db_get_table( 'project' );
  927. $t_bug_monitor_table = db_get_table( 'bug_monitor' );
  928. $t_limit_reporters = config_get( 'limit_reporters' );
  929. $t_bug_relationship_table = db_get_table( 'bug_relationship' );
  930. $t_report_bug_threshold = config_get( 'report_bug_threshold' );
  931. $t_where_param_count = 0;
  932. $t_current_user_id = auth_get_current_user_id();
  933. if( null === $p_user_id ) {
  934. $t_user_id = $t_current_user_id;
  935. } else {
  936. $t_user_id = $p_user_id;
  937. }
  938. $c_user_id = db_prepare_int( $t_user_id );
  939. if( null === $p_project_id ) {
  940. # @@@ If project_id is not specified, then use the project id(s) in the filter if set, otherwise, use current project.
  941. $t_project_id = helper_get_current_project();
  942. } else {
  943. $t_project_id = $p_project_id;
  944. }
  945. if( $p_custom_filter === null ) {
  946. # Prefer current_user_get_bug_filter() over user_get_filter() when applicable since it supports
  947. # cookies set by previous version of the code.
  948. if( $t_user_id == $t_current_user_id ) {
  949. $t_filter = current_user_get_bug_filter();
  950. } else {
  951. $t_filter = user_get_bug_filter( $t_user_id, $t_project_id );
  952. }
  953. } else {
  954. $t_filter = $p_custom_filter;
  955. }
  956. $t_filter = filter_ensure_valid_filter( $t_filter );
  957. if( false === $t_filter ) {
  958. return false;
  959. # signify a need to create a cookie
  960. # @@@ error instead?
  961. }
  962. $t_view_type = $t_filter['_view_type'];
  963. $t_where_clauses = array(
  964. "$t_project_table.enabled = " . db_param(),
  965. "$t_project_table.id = $t_bug_table.project_id",
  966. );
  967. $t_where_params = array(
  968. 1,
  969. );
  970. $t_select_clauses = array(
  971. "$t_bug_table.*",
  972. "$t_bug_table.last_updated",
  973. "$t_bug_table.date_submitted",
  974. );
  975. $t_join_clauses = array();
  976. $t_from_clauses = array();
  977. // normalize the project filtering into an array $t_project_ids
  978. if( 'simple' == $t_view_type ) {
  979. log_event( LOG_FILTERING, 'Simple Filter' );
  980. $t_project_ids = array(
  981. $t_project_id,
  982. );
  983. $t_include_sub_projects = true;
  984. } else {
  985. log_event( LOG_FILTERING, 'Advanced Filter' );
  986. if( !is_array( $t_filter[FILTER_PROPERTY_PROJECT_ID] ) ) {
  987. $t_project_ids = array(
  988. db_prepare_int( $t_filter[FILTER_PROPERTY_PROJECT_ID] ),
  989. );
  990. } else {
  991. $t_project_ids = array_map( 'db_prepare_int', $t_filter[FILTER_PROPERTY_PROJECT_ID] );
  992. }
  993. $t_include_sub_projects = (( count( $t_project_ids ) == 1 ) && ( $t_project_ids[0] == META_FILTER_CURRENT ) );
  994. }
  995. log_event( LOG_FILTERING, 'project_ids = @P' . implode( ', @P', $t_project_ids ) );
  996. log_event( LOG_FILTERING, 'include sub-projects = ' . ( $t_include_sub_projects ? '1' : '0' ) );
  997. // if the array has ALL_PROJECTS, then reset the array to only contain ALL_PROJECTS.
  998. // replace META_FILTER_CURRENT with the actualy current project id.
  999. $t_all_projects_found = false;
  1000. $t_new_project_ids = array();
  1001. foreach( $t_project_ids as $t_pid ) {
  1002. if( $t_pid == META_FILTER_CURRENT ) {
  1003. $t_pid = $t_project_id;
  1004. }
  1005. if( $t_pid == ALL_PROJECTS ) {
  1006. $t_all_projects_found = true;
  1007. log_event( LOG_FILTERING, 'all projects selected' );
  1008. break;
  1009. }
  1010. // filter out inaccessible projects.
  1011. if( !access_has_project_level( VIEWER, $t_pid, $t_user_id ) ) {
  1012. continue;
  1013. }
  1014. $t_new_project_ids[] = $t_pid;
  1015. }
  1016. $t_projects_query_required = true;
  1017. if( $t_all_projects_found ) {
  1018. if( user_is_administrator( $t_user_id ) ) {
  1019. log_event( LOG_FILTERING, 'all projects + administrator, hence no project filter.' );
  1020. $t_projects_query_required = false;
  1021. } else {
  1022. $t_project_ids = user_get_accessible_projects( $t_user_id );
  1023. }
  1024. } else {
  1025. $t_project_ids = $t_new_project_ids;
  1026. }
  1027. if( $t_projects_query_required ) {
  1028. // expand project ids to include sub-projects
  1029. if( $t_include_sub_projects ) {
  1030. $t_top_project_ids = $t_project_ids;
  1031. foreach( $t_top_project_ids as $t_pid ) {
  1032. log_event( LOG_FILTERING, 'Getting sub-projects for project id @P' . $t_pid );
  1033. $t_project_ids = array_merge( $t_project_ids, user_get_all_accessible_subprojects( $t_user_id, $t_pid ) );
  1034. }
  1035. $t_project_ids = array_unique( $t_project_ids );
  1036. }
  1037. // if no projects are accessible, then return an empty array.
  1038. if( count( $t_project_ids ) == 0 ) {
  1039. log_event( LOG_FILTERING, 'no accessible projects' );
  1040. return array();
  1041. }
  1042. log_event( LOG_FILTERING, 'project_ids after including sub-projects = @P' . implode( ', @P', $t_project_ids ) );
  1043. // this array is to be populated with project ids for which we only want to show public issues. This is due to the limited
  1044. // access of the current user.
  1045. $t_public_only_project_ids = array();
  1046. // this array is populated with project ids that the current user has full access to.
  1047. $t_private_and_public_project_ids = array();
  1048. $t_access_required_to_view_private_bugs = config_get( 'private_bug_threshold' );
  1049. foreach( $t_project_ids as $t_pid ) {
  1050. if( access_has_project_level( $t_access_required_to_view_private_bugs, $t_pid, $t_user_id ) ) {
  1051. $t_private_and_public_project_ids[] = $t_pid;
  1052. } else {
  1053. $t_public_only_project_ids[] = $t_pid;
  1054. }
  1055. }
  1056. log_event( LOG_FILTERING, 'project_ids (with public/private access) = @P' . implode( ', @P', $t_private_and_public_project_ids ) );
  1057. log_event( LOG_FILTERING, 'project_ids (with public access) = @P' . implode( ', @P', $t_public_only_project_ids ) );
  1058. $t_count_private_and_public_project_ids = count( $t_private_and_public_project_ids );
  1059. if( $t_count_private_and_public_project_ids == 1 ) {
  1060. $t_private_and_public_query = "( $t_bug_table.project_id = " . $t_private_and_public_project_ids[0] . " )";
  1061. }
  1062. else if( $t_count_private_and_public_project_ids > 1 ) {
  1063. $t_private_and_public_query = "( $t_bug_table.project_id in (" . implode( ', ', $t_private_and_public_project_ids ) . ") )";
  1064. } else {
  1065. $t_private_and_public_query = null;
  1066. }
  1067. $t_count_public_only_project_ids = count( $t_public_only_project_ids );
  1068. $t_public_view_state_check = "( ( $t_bug_table.view_state = " . VS_PUBLIC . " ) OR ( $t_bug_table.reporter_id = $t_user_id ) )";
  1069. if( $t_count_public_only_project_ids == 1 ) {
  1070. $t_public_only_query = "( ( $t_bug_table.project_id = " . $t_public_only_project_ids[0] . " ) AND $t_public_view_state_check )";
  1071. }
  1072. else if( $t_count_public_only_project_ids > 1 ) {
  1073. $t_public_only_query = "( ( $t_bug_table.project_id in (" . implode( ', ', $t_public_only_project_ids ) . ") ) AND $t_public_view_state_check )";
  1074. } else {
  1075. $t_public_only_query = null;
  1076. }
  1077. // both queries can't be null, so we either have one of them or both.
  1078. if( $t_private_and_public_query === null ) {
  1079. $t_project_query = $t_public_only_query;
  1080. } else if( $t_public_only_query === null ) {
  1081. $t_project_query = $t_private_and_public_query;
  1082. } else {
  1083. $t_project_query = "( $t_public_only_query OR $t_private_and_public_query )";
  1084. }
  1085. log_event( LOG_FILTERING, 'project query = ' . $t_project_query );
  1086. array_push( $t_where_clauses, $t_project_query );
  1087. }
  1088. # view state
  1089. $t_view_state = db_prepare_int( $t_filter[FILTER_PROPERTY_VIEW_STATE] );
  1090. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_VIEW_STATE] ) ) {
  1091. $t_view_state_query = "($t_bug_table.view_state=" . db_param() . ')';
  1092. log_event( LOG_FILTERING, 'view_state query = ' . $t_view_state_query );
  1093. $t_where_params[] = $t_view_state;
  1094. array_push( $t_where_clauses, $t_view_state_query );
  1095. } else {
  1096. log_event( LOG_FILTERING, 'no view_state query' );
  1097. }
  1098. # reporter
  1099. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_REPORTER_ID] ) ) {
  1100. $t_clauses = array();
  1101. foreach( $t_filter[FILTER_PROPERTY_REPORTER_ID] as $t_filter_member ) {
  1102. if( filter_field_is_none( $t_filter_member ) ) {
  1103. array_push( $t_clauses, "0" );
  1104. } else {
  1105. $c_reporter_id = db_prepare_int( $t_filter_member );
  1106. if( filter_field_is_myself( $c_reporter_id ) ) {
  1107. array_push( $t_clauses, $c_user_id );
  1108. } else {
  1109. array_push( $t_clauses, $c_reporter_id );
  1110. }
  1111. }
  1112. }
  1113. if( 1 < count( $t_clauses ) ) {
  1114. $t_reporter_query = "( $t_bug_table.reporter_id in (" . implode( ', ', $t_clauses ) . ") )";
  1115. } else {
  1116. $t_reporter_query = "( $t_bug_table.reporter_id=$t_clauses[0] )";
  1117. }
  1118. log_event( LOG_FILTERING, 'reporter query = ' . $t_reporter_query );
  1119. array_push( $t_where_clauses, $t_reporter_query );
  1120. } else {
  1121. log_event( LOG_FILTERING, 'no reporter query' );
  1122. }
  1123. # limit reporter
  1124. # @@@ thraxisp - access_has_project_level checks greater than or equal to,
  1125. # this assumed that there aren't any holes above REPORTER where the limit would apply
  1126. #
  1127. if(( ON === $t_limit_reporters ) && ( !access_has_project_level( REPORTER + 1, $t_project_id, $t_user_id ) ) ) {
  1128. $c_reporter_id = $c_user_id;
  1129. $t_where_params[] = $c_reporter_id;
  1130. array_push( $t_where_clauses, "($t_bug_table.reporter_id=" . db_param() . ')' );
  1131. }
  1132. # handler
  1133. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_HANDLER_ID] ) ) {
  1134. $t_clauses = array();
  1135. foreach( $t_filter[FILTER_PROPERTY_HANDLER_ID] as $t_filter_member ) {
  1136. if( filter_field_is_none( $t_filter_member ) ) {
  1137. array_push( $t_clauses, 0 );
  1138. } else {
  1139. $c_handler_id = db_prepare_int( $t_filter_member );
  1140. if( filter_field_is_myself( $c_handler_id ) ) {
  1141. array_push( $t_clauses, $c_user_id );
  1142. } else {
  1143. array_push( $t_clauses, $c_handler_id );
  1144. }
  1145. }
  1146. }
  1147. if( 1 < count( $t_clauses ) ) {
  1148. $t_handler_query = "( $t_bug_table.handler_id in (" . implode( ', ', $t_clauses ) . ") )";
  1149. } else {
  1150. $t_handler_query = "( $t_bug_table.handler_id=$t_clauses[0] )";
  1151. }
  1152. log_event( LOG_FILTERING, 'handler query = ' . $t_handler_query );
  1153. array_push( $t_where_clauses, $t_handler_query );
  1154. } else {
  1155. log_event( LOG_FILTERING, 'no handler query' );
  1156. }
  1157. # category
  1158. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_CATEGORY_ID] ) ) {
  1159. $t_clauses = array();
  1160. foreach( $t_filter[FILTER_PROPERTY_CATEGORY_ID] as $t_filter_member ) {
  1161. if( !filter_field_is_none( $t_filter_member ) ) {
  1162. array_push( $t_clauses, $t_filter_member );
  1163. }
  1164. }
  1165. if( 1 < count( $t_clauses ) ) {
  1166. $t_where_tmp = array();
  1167. foreach( $t_clauses as $t_clause ) {
  1168. $t_where_tmp[] = db_param();
  1169. $t_where_params[] = $t_clause;
  1170. }
  1171. array_push( $t_where_clauses, "( $t_bug_table.category_id in ( SELECT id FROM $t_category_table WHERE name in (" . implode( ', ', $t_where_tmp ) . ") ) )" );
  1172. } else {
  1173. $t_where_params[] = $t_clauses[0];
  1174. array_push( $t_where_clauses, "( $t_bug_table.category_id in ( SELECT id FROM $t_category_table WHERE name=" . db_param() . ") )" );
  1175. }
  1176. }
  1177. # severity
  1178. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_SEVERITY] ) ) {
  1179. $t_clauses = array();
  1180. foreach( $t_filter[FILTER_PROPERTY_SEVERITY] as $t_filter_member ) {
  1181. $c_show_severity = db_prepare_int( $t_filter_member );
  1182. array_push( $t_clauses, $c_show_severity );
  1183. }
  1184. if( 1 < count( $t_clauses ) ) {
  1185. $t_where_tmp = array();
  1186. foreach( $t_clauses as $t_clause ) {
  1187. $t_where_tmp[] = db_param();
  1188. $t_where_params[] = $t_clause;
  1189. }
  1190. array_push( $t_where_clauses, "( $t_bug_table.severity in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1191. } else {
  1192. $t_where_params[] = $t_clauses[0];
  1193. array_push( $t_where_clauses, "( $t_bug_table.severity=" . db_param() . " )" );
  1194. }
  1195. }
  1196. # show / hide status
  1197. # take a list of all available statuses then remove the ones that we want hidden, then make sure
  1198. # the ones we want shown are still available
  1199. $t_desired_statuses = array();
  1200. $t_available_statuses = MantisEnum::getValues( config_get( 'status_enum_string' ) );
  1201. if( 'simple' == $t_filter['_view_type'] ) {
  1202. # simple filtering: if showing any, restrict by the hide status value, otherwise ignore the hide
  1203. $t_any_found = false;
  1204. $t_this_status = $t_filter[FILTER_PROPERTY_STATUS][0];
  1205. $t_this_hide_status = $t_filter[FILTER_PROPERTY_HIDE_STATUS][0];
  1206. if( filter_field_is_any( $t_this_status ) ) {
  1207. foreach( $t_available_statuses as $t_this_available_status ) {
  1208. if( $t_this_hide_status > $t_this_available_status ) {
  1209. $t_desired_statuses[] = $t_this_available_status;
  1210. }
  1211. }
  1212. } else {
  1213. $t_desired_statuses[] = $t_this_status;
  1214. }
  1215. } else {
  1216. # advanced filtering: ignore the hide
  1217. if( filter_field_is_any( $t_filter[FILTER_PROPERTY_STATUS] ) ) {
  1218. $t_desired_statuses = array();
  1219. } else {
  1220. foreach( $t_filter[FILTER_PROPERTY_STATUS] as $t_this_status ) {
  1221. $t_desired_statuses[] = $t_this_status;
  1222. }
  1223. }
  1224. }
  1225. if( count( $t_desired_statuses ) > 0 ) {
  1226. $t_clauses = array();
  1227. foreach( $t_desired_statuses as $t_filter_member ) {
  1228. $c_show_status = db_prepare_int( $t_filter_member );
  1229. array_push( $t_clauses, $c_show_status );
  1230. }
  1231. if( 1 < count( $t_clauses ) ) {
  1232. $t_where_tmp = array();
  1233. foreach( $t_clauses as $t_clause ) {
  1234. $t_where_tmp[] = db_param();
  1235. $t_where_params[] = $t_clause;
  1236. }
  1237. array_push( $t_where_clauses, "( $t_bug_table.status in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1238. } else {
  1239. $t_where_params[] = $t_clauses[0];
  1240. array_push( $t_where_clauses, "( $t_bug_table.status=" . db_param() . " )" );
  1241. }
  1242. }
  1243. # resolution
  1244. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_RESOLUTION] ) ) {
  1245. $t_clauses = array();
  1246. foreach( $t_filter[FILTER_PROPERTY_RESOLUTION] as $t_filter_member ) {
  1247. $c_show_resolution = db_prepare_int( $t_filter_member );
  1248. array_push( $t_clauses, $c_show_resolution );
  1249. }
  1250. if( 1 < count( $t_clauses ) ) {
  1251. $t_where_tmp = array();
  1252. foreach( $t_clauses as $t_clause ) {
  1253. $t_where_tmp[] = db_param();
  1254. $t_where_params[] = $t_clause;
  1255. }
  1256. array_push( $t_where_clauses, "( $t_bug_table.resolution in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1257. } else {
  1258. $t_where_params[] = $t_clauses[0];
  1259. array_push( $t_where_clauses, "( $t_bug_table.resolution=" . db_param() . " )" );
  1260. }
  1261. }
  1262. # priority
  1263. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_PRIORITY] ) ) {
  1264. $t_clauses = array();
  1265. foreach( $t_filter[FILTER_PROPERTY_PRIORITY] as $t_filter_member ) {
  1266. $c_show_priority = db_prepare_int( $t_filter_member );
  1267. array_push( $t_clauses, $c_show_priority );
  1268. }
  1269. if( 1 < count( $t_clauses ) ) {
  1270. $t_where_tmp = array();
  1271. foreach( $t_clauses as $t_clause ) {
  1272. $t_where_tmp[] = db_param();
  1273. $t_where_params[] = $t_clause;
  1274. }
  1275. array_push( $t_where_clauses, "( $t_bug_table.priority in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1276. } else {
  1277. $t_where_params[] = $t_clauses[0];
  1278. array_push( $t_where_clauses, "( $t_bug_table.priority=" . db_param() . " )" );
  1279. }
  1280. }
  1281. # product build
  1282. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_BUILD] ) ) {
  1283. $t_clauses = array();
  1284. foreach( $t_filter[FILTER_PROPERTY_BUILD] as $t_filter_member ) {
  1285. $t_filter_member = stripslashes( $t_filter_member );
  1286. if( filter_field_is_none( $t_filter_member ) ) {
  1287. array_push( $t_clauses, '' );
  1288. } else {
  1289. $c_show_build = db_prepare_string( $t_filter_member );
  1290. array_push( $t_clauses, $c_show_build );
  1291. }
  1292. }
  1293. if( 1 < count( $t_clauses ) ) {
  1294. $t_where_tmp = array();
  1295. foreach( $t_clauses as $t_clause ) {
  1296. $t_where_tmp[] = db_param();
  1297. $t_where_params[] = $t_clause;
  1298. }
  1299. array_push( $t_where_clauses, "( $t_bug_table.build in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1300. } else {
  1301. $t_where_params[] = $t_clauses[0];
  1302. array_push( $t_where_clauses, "( $t_bug_table.build=" . db_param() . " )" );
  1303. }
  1304. }
  1305. # product version
  1306. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_VERSION] ) ) {
  1307. $t_clauses = array();
  1308. foreach( $t_filter[FILTER_PROPERTY_VERSION] as $t_filter_member ) {
  1309. $t_filter_member = stripslashes( $t_filter_member );
  1310. if( filter_field_is_none( $t_filter_member ) ) {
  1311. array_push( $t_clauses, '' );
  1312. } else {
  1313. $c_show_version = db_prepare_string( $t_filter_member );
  1314. array_push( $t_clauses, $c_show_version );
  1315. }
  1316. }
  1317. if( 1 < count( $t_clauses ) ) {
  1318. $t_where_tmp = array();
  1319. foreach( $t_clauses as $t_clause ) {
  1320. $t_where_tmp[] = db_param();
  1321. $t_where_params[] = $t_clause;
  1322. }
  1323. array_push( $t_where_clauses, "( $t_bug_table.version in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1324. } else {
  1325. $t_where_params[] = $t_clauses[0];
  1326. array_push( $t_where_clauses, "( $t_bug_table.version=" . db_param() . " )" );
  1327. }
  1328. }
  1329. # profile
  1330. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_PROFILE_ID] ) ) {
  1331. $t_clauses = array();
  1332. foreach( $t_filter[FILTER_PROPERTY_PROFILE_ID] as $t_filter_member ) {
  1333. $t_filter_member = stripslashes( $t_filter_member );
  1334. if( filter_field_is_none( $t_filter_member ) ) {
  1335. array_push( $t_clauses, "0" );
  1336. } else {
  1337. $c_show_profile = db_prepare_int( $t_filter_member );
  1338. array_push( $t_clauses, "$c_show_profile" );
  1339. }
  1340. }
  1341. if( 1 < count( $t_clauses ) ) {
  1342. $t_where_tmp = array();
  1343. foreach( $t_clauses as $t_clause ) {
  1344. $t_where_tmp[] = db_param();
  1345. $t_where_params[] = $t_clause;
  1346. }
  1347. array_push( $t_where_clauses, "( $t_bug_table.profile_id in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1348. } else {
  1349. $t_where_params[] = $t_clauses[0];
  1350. array_push( $t_where_clauses, "( $t_bug_table.profile_id=" . db_param() . " )" );
  1351. }
  1352. }
  1353. # platform
  1354. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_PLATFORM] ) ) {
  1355. $t_clauses = array();
  1356. foreach( $t_filter[FILTER_PROPERTY_PLATFORM] as $t_filter_member ) {
  1357. $t_filter_member = stripslashes( $t_filter_member );
  1358. if( filter_field_is_none( $t_filter_member ) ) {
  1359. array_push( $t_clauses, '' );
  1360. } else {
  1361. $c_platform = db_prepare_string( $t_filter_member );
  1362. array_push( $t_clauses, $c_platform );
  1363. }
  1364. }
  1365. if( 1 < count( $t_clauses ) ) {
  1366. $t_where_tmp = array();
  1367. foreach( $t_clauses as $t_clause ) {
  1368. $t_where_tmp[] = db_param();
  1369. $t_where_params[] = $t_clause;
  1370. }
  1371. array_push( $t_where_clauses, "( $t_bug_table.platform in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1372. } else {
  1373. $t_where_params[] = $t_clauses[0];
  1374. array_push( $t_where_clauses, "( $t_bug_table.platform = " . db_param() . " )" );
  1375. }
  1376. }
  1377. # os
  1378. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_OS] ) ) {
  1379. $t_clauses = array();
  1380. foreach( $t_filter[FILTER_PROPERTY_OS] as $t_filter_member ) {
  1381. $t_filter_member = stripslashes( $t_filter_member );
  1382. if( filter_field_is_none( $t_filter_member ) ) {
  1383. array_push( $t_clauses, '' );
  1384. } else {
  1385. $c_os = db_prepare_string( $t_filter_member );
  1386. array_push( $t_clauses, $c_os );
  1387. }
  1388. }
  1389. if( 1 < count( $t_clauses ) ) {
  1390. $t_where_tmp = array();
  1391. foreach( $t_clauses as $t_clause ) {
  1392. $t_where_tmp[] = db_param();
  1393. $t_where_params[] = $t_clause;
  1394. }
  1395. array_push( $t_where_clauses, "( $t_bug_table.os in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1396. } else {
  1397. $t_where_params[] = $t_clauses[0];
  1398. array_push( $t_where_clauses, "( $t_bug_table.os = " . db_param() . " )" );
  1399. }
  1400. }
  1401. # os_build
  1402. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_OS_BUILD] ) ) {
  1403. $t_clauses = array();
  1404. foreach( $t_filter[FILTER_PROPERTY_OS_BUILD] as $t_filter_member ) {
  1405. $t_filter_member = stripslashes( $t_filter_member );
  1406. if( filter_field_is_none( $t_filter_member ) ) {
  1407. array_push( $t_clauses, '' );
  1408. } else {
  1409. $c_os_build = db_prepare_string( $t_filter_member );
  1410. array_push( $t_clauses, $c_os_build );
  1411. }
  1412. }
  1413. if( 1 < count( $t_clauses ) ) {
  1414. $t_where_tmp = array();
  1415. foreach( $t_clauses as $t_clause ) {
  1416. $t_where_tmp[] = db_param();
  1417. $t_where_params[] = $t_clause;
  1418. }
  1419. array_push( $t_where_clauses, "( $t_bug_table.os_build in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1420. } else {
  1421. $t_where_params[] = $t_clauses[0];
  1422. array_push( $t_where_clauses, "( $t_bug_table.os_build = " . db_param() . " )" );
  1423. }
  1424. }
  1425. # date filter
  1426. if(( 'on' == $t_filter[FILTER_PROPERTY_FILTER_BY_DATE] ) && is_numeric( $t_filter[FILTER_PROPERTY_START_MONTH] ) && is_numeric( $t_filter[FILTER_PROPERTY_START_DAY] ) && is_numeric( $t_filter[FILTER_PROPERTY_START_YEAR] ) && is_numeric( $t_filter[FILTER_PROPERTY_END_MONTH] ) && is_numeric( $t_filter[FILTER_PROPERTY_END_DAY] ) && is_numeric( $t_filter[FILTER_PROPERTY_END_YEAR] ) ) {
  1427. $t_start_string = $t_filter[FILTER_PROPERTY_START_YEAR] . "-" . $t_filter[FILTER_PROPERTY_START_MONTH] . "-" . $t_filter[FILTER_PROPERTY_START_DAY] . " 00:00:00";
  1428. $t_end_string = $t_filter[FILTER_PROPERTY_END_YEAR] . "-" . $t_filter[FILTER_PROPERTY_END_MONTH] . "-" . $t_filter[FILTER_PROPERTY_END_DAY] . " 23:59:59";
  1429. $t_where_params[] = strtotime( $t_start_string );
  1430. $t_where_params[] = strtotime( $t_end_string );
  1431. array_push( $t_where_clauses, "($t_bug_table.date_submitted BETWEEN " . db_param() . " AND " . db_param() . " )" );
  1432. }
  1433. # fixed in version
  1434. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION] ) ) {
  1435. $t_clauses = array();
  1436. foreach( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION] as $t_filter_member ) {
  1437. $t_filter_member = stripslashes( $t_filter_member );
  1438. if( filter_field_is_none( $t_filter_member ) ) {
  1439. array_push( $t_clauses, '' );
  1440. } else {
  1441. $c_fixed_in_version = db_prepare_string( $t_filter_member );
  1442. array_push( $t_clauses, $c_fixed_in_version );
  1443. }
  1444. }
  1445. if( 1 < count( $t_clauses ) ) {
  1446. $t_where_tmp = array();
  1447. foreach( $t_clauses as $t_clause ) {
  1448. $t_where_tmp[] = db_param();
  1449. $t_where_params[] = $t_clause;
  1450. }
  1451. array_push( $t_where_clauses, "( $t_bug_table.fixed_in_version in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1452. } else {
  1453. $t_where_params[] = $t_clauses[0];
  1454. array_push( $t_where_clauses, "( $t_bug_table.fixed_in_version=" . db_param() . " )" );
  1455. }
  1456. }
  1457. # target version
  1458. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_TARGET_VERSION] ) ) {
  1459. $t_clauses = array();
  1460. foreach( $t_filter[FILTER_PROPERTY_TARGET_VERSION] as $t_filter_member ) {
  1461. $t_filter_member = stripslashes( $t_filter_member );
  1462. if( filter_field_is_none( $t_filter_member ) ) {
  1463. array_push( $t_clauses, '' );
  1464. } else {
  1465. $c_target_version = db_prepare_string( $t_filter_member );
  1466. array_push( $t_clauses, $c_target_version );
  1467. }
  1468. }
  1469. # echo var_dump( $t_clauses ); exit;
  1470. if( 1 < count( $t_clauses ) ) {
  1471. $t_where_tmp = array();
  1472. foreach( $t_clauses as $t_clause ) {
  1473. $t_where_tmp[] = db_param();
  1474. $t_where_params[] = $t_clause;
  1475. }
  1476. array_push( $t_where_clauses, "( $t_bug_table.target_version in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1477. } else {
  1478. $t_where_params[] = $t_clauses[0];
  1479. array_push( $t_where_clauses, "( $t_bug_table.target_version=" . db_param() . " )" );
  1480. }
  1481. }
  1482. # users monitoring a bug
  1483. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID] ) ) {
  1484. $t_clauses = array();
  1485. $t_table_name = 'user_monitor';
  1486. array_push( $t_join_clauses, "LEFT JOIN $t_bug_monitor_table $t_table_name ON $t_table_name.bug_id = $t_bug_table.id" );
  1487. foreach( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID] as $t_filter_member ) {
  1488. $c_user_monitor = db_prepare_int( $t_filter_member );
  1489. if( filter_field_is_myself( $c_user_monitor ) ) {
  1490. array_push( $t_clauses, $c_user_id );
  1491. } else {
  1492. array_push( $t_clauses, $c_user_monitor );
  1493. }
  1494. }
  1495. if( 1 < count( $t_clauses ) ) {
  1496. $t_where_tmp = array();
  1497. foreach( $t_clauses as $t_clause ) {
  1498. $t_where_tmp[] = db_param();
  1499. $t_where_params[] = $t_clause;
  1500. }
  1501. array_push( $t_where_clauses, "( $t_table_name.user_id in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1502. } else {
  1503. $t_where_params[] = $t_clauses[0];
  1504. array_push( $t_where_clauses, "( $t_table_name.user_id=" . db_param() . " )" );
  1505. }
  1506. }
  1507. # bug relationship
  1508. $t_any_found = false;
  1509. $c_rel_type = $t_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE];
  1510. $c_rel_bug = $t_filter[FILTER_PROPERTY_RELATIONSHIP_BUG];
  1511. if( -1 == $c_rel_type || 0 == $c_rel_bug ) {
  1512. $t_any_found = true;
  1513. }
  1514. if( !$t_any_found ) {
  1515. # use the complementary type
  1516. $t_comp_type = relationship_get_complementary_type( $c_rel_type );
  1517. $t_clauses = array();
  1518. $t_table_name = 'relationship';
  1519. array_push( $t_join_clauses, "LEFT JOIN $t_bug_relationship_table $t_table_name ON $t_table_name.destination_bug_id = $t_bug_table.id" );
  1520. array_push( $t_join_clauses, "LEFT JOIN $t_bug_relationship_table ${t_table_name}2 ON ${t_table_name}2.source_bug_id = $t_bug_table.id" );
  1521. // get reverse relationships
  1522. $t_where_params[] = $t_comp_type;
  1523. $t_where_params[] = $c_rel_bug;
  1524. $t_where_params[] = $c_rel_type;
  1525. $t_where_params[] = $c_rel_bug;
  1526. array_push( $t_clauses, "($t_table_name.relationship_type=" . db_param() . " AND $t_table_name.source_bug_id=" . db_param() . ')' );
  1527. array_push( $t_clauses, "($t_table_name" . "2.relationship_type=" . db_param() . " AND $t_table_name" . "2.destination_bug_id=" . db_param() . ')' );
  1528. array_push( $t_where_clauses, '(' . implode( ' OR ', $t_clauses ) . ')' );
  1529. }
  1530. # tags
  1531. $c_tag_string = trim( $t_filter[FILTER_PROPERTY_TAG_STRING] );
  1532. $c_tag_select = trim( $t_filter[FILTER_PROPERTY_TAG_SELECT] );
  1533. if( is_blank( $c_tag_string ) && !is_blank( $c_tag_select ) && $c_tag_select != 0 ) {
  1534. $t_tag = tag_get( $c_tag_select );
  1535. $c_tag_string = $t_tag['name'];
  1536. }
  1537. if( !is_blank( $c_tag_string ) ) {
  1538. $t_tags = tag_parse_filters( $c_tag_string );
  1539. if( count( $t_tags ) ) {
  1540. $t_tags_all = array();
  1541. $t_tags_any = array();
  1542. $t_tags_none = array();
  1543. foreach( $t_tags as $t_tag_row ) {
  1544. switch( $t_tag_row['filter'] ) {
  1545. case 1:
  1546. $t_tags_all[] = $t_tag_row;
  1547. break;
  1548. case 0:
  1549. $t_tags_any[] = $t_tag_row;
  1550. break;
  1551. case -1:
  1552. $t_tags_none[] = $t_tag_row;
  1553. break;
  1554. }
  1555. }
  1556. if( 0 < $t_filter[FILTER_PROPERTY_TAG_SELECT] && tag_exists( $t_filter[FILTER_PROPERTY_TAG_SELECT] ) ) {
  1557. $t_tags_any[] = tag_get( $t_filter[FILTER_PROPERTY_TAG_SELECT] );
  1558. }
  1559. $t_bug_tag_table = db_get_table( 'bug_tag' );
  1560. if( count( $t_tags_all ) ) {
  1561. $t_clauses = array();
  1562. foreach( $t_tags_all as $t_tag_row ) {
  1563. array_push( $t_clauses, "$t_bug_table.id IN ( SELECT bug_id FROM $t_bug_tag_table WHERE $t_bug_tag_table.tag_id = $t_tag_row[id] )" );
  1564. }
  1565. array_push( $t_where_clauses, '(' . implode( ' AND ', $t_clauses ) . ')' );
  1566. }
  1567. if( count( $t_tags_any ) ) {
  1568. $t_clauses = array();
  1569. foreach( $t_tags_any as $t_tag_row ) {
  1570. array_push( $t_clauses, "$t_bug_tag_table.tag_id = $t_tag_row[id]" );
  1571. }
  1572. array_push( $t_where_clauses, "$t_bug_table.id IN ( SELECT bug_id FROM $t_bug_tag_table WHERE ( " . implode( ' OR ', $t_clauses ) . ') )' );
  1573. }
  1574. if( count( $t_tags_none ) ) {
  1575. $t_clauses = array();
  1576. foreach( $t_tags_none as $t_tag_row ) {
  1577. array_push( $t_clauses, "$t_bug_tag_table.tag_id = $t_tag_row[id]" );
  1578. }
  1579. array_push( $t_where_clauses, "$t_bug_table.id NOT IN ( SELECT bug_id FROM $t_bug_tag_table WHERE ( " . implode( ' OR ', $t_clauses ) . ') )' );
  1580. }
  1581. }
  1582. }
  1583. # note user id
  1584. if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_NOTE_USER_ID] ) ) {
  1585. $t_bugnote_table_alias = 'mbnt';
  1586. $t_clauses = array();
  1587. array_push( $t_from_clauses, "$t_bugnote_table $t_bugnote_table_alias" );
  1588. array_push( $t_where_clauses, "( $t_bug_table.id = $t_bugnote_table_alias.bug_id )" );
  1589. foreach( $t_filter[FILTER_PROPERTY_NOTE_USER_ID] as $t_filter_member ) {
  1590. $c_note_user_id = db_prepare_int( $t_filter_member );
  1591. if( filter_field_is_myself( $c_note_user_id ) ) {
  1592. array_push( $t_clauses, $c_user_id );
  1593. } else {
  1594. array_push( $t_clauses, $c_note_user_id );
  1595. }
  1596. }
  1597. if( 1 < count( $t_clauses ) ) {
  1598. $t_where_tmp = array();
  1599. foreach( $t_clauses as $t_clause ) {
  1600. $t_where_tmp[] = db_param();
  1601. $t_where_params[] = $t_clause;
  1602. }
  1603. array_push( $t_where_clauses, "( $t_bugnote_table_alias.reporter_id in (" . implode( ', ', $t_where_tmp ) . ") )" );
  1604. } else {
  1605. $t_where_params[] = $t_clauses[0];
  1606. array_push( $t_where_clauses, "( $t_bugnote_table_alias.reporter_id=" . db_param() . " )" );
  1607. }
  1608. }
  1609. # plugin filters
  1610. $t_plugin_filters = filter_get_plugin_filters();
  1611. foreach( $t_plugin_filters as $t_field_name => $t_filter_object ) {
  1612. if ( !filter_field_is_any( $t_filter[ $t_field_name ] ) || $t_filter_object->type == FILTER_TYPE_BOOLEAN ) {
  1613. $t_filter_query = $t_filter_object->query( $t_filter[ $t_field_name ] );
  1614. if ( is_array( $t_filter_query ) ) {
  1615. if ( isset( $t_filter_query['join'] ) ) {
  1616. array_push( $t_join_clauses, $t_filter_query['join'] );
  1617. }
  1618. if ( isset( $t_filter_query['where'] ) ) {
  1619. array_push( $t_where_clauses, $t_filter_query['where'] );
  1620. }
  1621. if ( isset( $t_filter_query['params'] ) && is_array( $t_filter_query['params'] ) ) {
  1622. array_merge( $t_where_params, $t_filter_query['params'] );
  1623. }
  1624. }
  1625. }
  1626. }
  1627. # custom field filters
  1628. if( ON == config_get( 'filter_by_custom_fields' ) ) {
  1629. # custom field filtering
  1630. # @@@ At the moment this gets the linked fields relating to the current project
  1631. # It should get the ones relating to the project in the filter or all projects
  1632. # if multiple projects.
  1633. $t_custom_fields = custom_field_get_linked_ids( $t_project_id );
  1634. foreach( $t_custom_fields as $t_cfid ) {
  1635. $t_field_info = custom_field_cache_row( $t_cfid, true );
  1636. if( !$t_field_info['filter_by'] ) {
  1637. continue;
  1638. # skip this custom field it shouldn't be filterable
  1639. }
  1640. $t_custom_where_clause = '';
  1641. # Ignore all custom filters that are not set, or that are set to '' or "any"
  1642. if( !filter_field_is_any( $t_filter['custom_fields'][$t_cfid] ) ) {
  1643. $t_def = custom_field_get_definition( $t_cfid );
  1644. $t_table_name = $t_custom_field_string_table . '_' . $t_cfid;
  1645. # We need to filter each joined table or the result query will explode in dimensions
  1646. # Each custom field will result in a exponential growth like Number_of_Issues^Number_of_Custom_Fields
  1647. # and only after this process ends (if it is able to) the result query will be filtered
  1648. # by the WHERE clause and by the DISTINCT clause
  1649. $t_cf_join_clause = "LEFT JOIN $t_custom_field_string_table $t_table_name ON $t_table_name.bug_id = $t_bug_table.id AND $t_table_name.field_id = $t_cfid ";
  1650. if( $t_def['type'] == CUSTOM_FIELD_TYPE_DATE ) {
  1651. switch( $t_filter['custom_fields'][$t_cfid][0] ) {
  1652. case CUSTOM_FIELD_DATE_ANY:
  1653. break;
  1654. case CUSTOM_FIELD_DATE_NONE:
  1655. array_push( $t_join_clauses, $t_cf_join_clause );
  1656. $t_custom_where_clause = '(( ' . $t_table_name . '.bug_id is null) OR ( ' . $t_table_name . '.value = 0)';
  1657. break;
  1658. case CUSTOM_FIELD_DATE_BEFORE:
  1659. array_push( $t_join_clauses, $t_cf_join_clause );
  1660. $t_custom_where_clause = '(( ' . $t_table_name . '.value != 0 AND (' . $t_table_name . '.value+0) < ' . ( $t_filter['custom_fields'][$t_cfid][2] ) . ')';
  1661. break;
  1662. case CUSTOM_FIELD_DATE_AFTER:
  1663. array_push( $t_join_clauses, $t_cf_join_clause );
  1664. $t_custom_where_clause = '( (' . $t_table_name . '.value+0) > ' . ( $t_filter['custom_fields'][$t_cfid][1] + 1 );
  1665. break;
  1666. default:
  1667. array_push( $t_join_clauses, $t_cf_join_clause );
  1668. $t_custom_where_clause = '( (' . $t_table_name . '.value+0) BETWEEN ' . $t_filter['custom_fields'][$t_cfid][1] . ' AND ' . $t_filter['custom_fields'][$t_cfid][2];
  1669. break;
  1670. }
  1671. } else {
  1672. array_push( $t_join_clauses, $t_cf_join_clause );
  1673. $t_filter_array = array();
  1674. foreach( $t_filter['custom_fields'][$t_cfid] as $t_filter_member ) {
  1675. $t_filter_member = stripslashes( $t_filter_member );
  1676. if( filter_field_is_none( $t_filter_member ) ) {
  1677. # coerce filter value if selecting META_FILTER_NONE so it will match empty fields
  1678. $t_filter_member = '';
  1679. # but also add those _not_ present in the custom field string table
  1680. array_push( $t_filter_array, "$t_bug_table.id NOT IN (SELECT bug_id FROM $t_custom_field_string_table WHERE field_id=$t_cfid)" );
  1681. }
  1682. switch( $t_def['type'] ) {
  1683. case CUSTOM_FIELD_TYPE_CHECKBOX:
  1684. case CUSTOM_FIELD_TYPE_MULTILIST:
  1685. $t_where_params[] = '%|' . $t_filter_member . '|%';
  1686. array_push( $t_filter_array, db_helper_like( "$t_table_name.value" ) );
  1687. break;
  1688. default:
  1689. array_push( $t_filter_array, "$t_table_name.value = '" . db_prepare_string( $t_filter_member ) . "'" );
  1690. }
  1691. }
  1692. $t_custom_where_clause .= '(' . implode( ' OR ', $t_filter_array );
  1693. }
  1694. if( !is_blank( $t_custom_where_clause ) ) {
  1695. array_push( $t_where_clauses, $t_custom_where_clause . ')' );
  1696. }
  1697. }
  1698. }
  1699. }
  1700. # Text search
  1701. if( !is_blank( $t_filter[FILTER_PROPERTY_SEARCH] ) ) {
  1702. # break up search terms by spacing or quoting
  1703. preg_match_all( "/-?([^'\"\s]+|\"[^\"]+\"|'[^']+')/", $t_filter[FILTER_PROPERTY_SEARCH], $t_matches, PREG_SET_ORDER );
  1704. # organize terms without quoting, paying attention to negation
  1705. $t_search_terms = array();
  1706. foreach( $t_matches as $t_match ) {
  1707. $t_search_terms[ trim( $t_match[1], "\'\"" ) ] = ( $t_match[0][0] == '-' );
  1708. }
  1709. # build a big where-clause and param list for all search terms, including negations
  1710. $t_first = true;
  1711. $t_textsearch_where_clause = "( ";
  1712. foreach( $t_search_terms as $t_search_term => $t_negate ) {
  1713. if ( !$t_first ) {
  1714. $t_textsearch_where_clause .= ' AND ';
  1715. }
  1716. if ( $t_negate ) {
  1717. $t_textsearch_where_clause .= 'NOT ';
  1718. }
  1719. $c_search = '%' . $t_search_term . '%';
  1720. $t_textsearch_where_clause .= '( ' . db_helper_like( 'summary' ) .
  1721. ' OR ' . db_helper_like( "$t_bug_text_table.description" ) .
  1722. ' OR ' . db_helper_like( "$t_bug_text_table.steps_to_reproduce" ) .
  1723. ' OR ' . db_helper_like( "$t_bug_text_table.additional_information" ) .
  1724. ' OR ' . db_helper_like( "$t_bugnote_text_table.note" );
  1725. $t_where_params[] = $c_search;
  1726. $t_where_params[] = $c_search;
  1727. $t_where_params[] = $c_search;
  1728. $t_where_params[] = $c_search;
  1729. $t_where_params[] = $c_search;
  1730. if( is_numeric( $t_search_term ) ) {
  1731. $c_search_int = (int) $t_search_term;
  1732. $t_textsearch_where_clause .= " OR $t_bug_table.id = " . db_param();
  1733. $t_textsearch_where_clause .= " OR $t_bugnote_table.id = " . db_param();
  1734. $t_where_params[] = $c_search_int;
  1735. $t_where_params[] = $c_search_int;
  1736. }
  1737. $t_textsearch_where_clause .= ' )';
  1738. $t_first = false;
  1739. }
  1740. $t_textsearch_where_clause .= ' )';
  1741. # add text query elements to arrays
  1742. if ( !$t_first ) {
  1743. $t_from_clauses[] = "$t_bug_text_table";
  1744. $t_where_clauses[] = "$t_bug_table.bug_text_id = $t_bug_text_table.id";
  1745. $t_where_clauses[] = $t_textsearch_where_clause;
  1746. $t_join_clauses[] = " LEFT JOIN $t_bugnote_table ON $t_bug_table.id = $t_bugnote_table.bug_id";
  1747. $t_join_clauses[] = " LEFT JOIN $t_bugnote_text_table ON $t_bugnote_table.bugnote_text_id = $t_bugnote_text_table.id";
  1748. }
  1749. }
  1750. # End text search
  1751. $t_from_clauses[] = $t_project_table;
  1752. $t_from_clauses[] = $t_bug_table;
  1753. $t_query_clauses['select'] = $t_select_clauses;
  1754. $t_query_clauses['from'] = $t_from_clauses;
  1755. $t_query_clauses['join'] = $t_join_clauses;
  1756. $t_query_clauses['where'] = $t_where_clauses;
  1757. $t_query_clauses['where_values'] = $t_where_params;
  1758. $t_query_clauses = filter_get_query_sort_data( $t_filter, $p_show_sticky, $t_query_clauses );
  1759. # assigning to $p_* for this function writes the values back in case the caller wants to know
  1760. # Get the total number of bugs that meet the criteria.
  1761. $p_bug_count = filter_get_bug_count( $t_query_clauses );
  1762. if( 0 == $p_bug_count ) {
  1763. return array();
  1764. }
  1765. $p_per_page = filter_per_page( $t_filter, $p_bug_count, $p_per_page );
  1766. $p_page_count = filter_page_count( $p_bug_count, $p_per_page );
  1767. $p_page_number = filter_valid_page_number( $p_page_number, $p_page_count );
  1768. $t_offset = filter_offset( $p_page_number, $p_per_page );
  1769. $t_query_clauses = filter_unique_query_clauses( $t_query_clauses );
  1770. $t_select_string = "SELECT DISTINCT " . implode( ', ', $t_query_clauses['select'] );
  1771. $t_from_string = " FROM " . implode( ', ', $t_query_clauses['from'] );
  1772. $t_order_string = " ORDER BY " . implode( ', ', $t_query_clauses['order'] );
  1773. $t_join_string = count( $t_query_clauses['join'] ) > 0 ? implode( ' ', $t_query_clauses['join'] ) : '';
  1774. $t_where_string = count( $t_query_clauses['where'] ) > 0 ? 'WHERE ' . implode( ' AND ', $t_query_clauses['where'] ) : '';
  1775. $t_result = db_query_bound( "$t_select_string $t_from_string $t_join_string $t_where_string $t_order_string", $t_query_clauses['where_values'], $p_per_page, $t_offset );
  1776. $t_row_count = db_num_rows( $t_result );
  1777. $t_id_array_lastmod = array();
  1778. for( $i = 0;$i < $t_row_count;$i++ ) {
  1779. $t_row = db_fetch_array( $t_result );
  1780. $t_id_array_lastmod[] = (int) $t_row['id'];
  1781. $t_rows[] = $t_row;
  1782. }
  1783. return filter_cache_result( $t_rows, $t_id_array_lastmod );
  1784. }
  1785. /**
  1786. * Cache the filter results with bugnote stats for later use
  1787. * @param array $p_rows results of the filter query
  1788. * @param array $p_id_array_lastmod array of bug ids
  1789. * @return array
  1790. */
  1791. function filter_cache_result( $p_rows, $p_id_array_lastmod ) {
  1792. $t_bugnote_table = db_get_table( 'bugnote' );
  1793. $t_id_array_lastmod = array_unique( $p_id_array_lastmod );
  1794. $t_where_string = "WHERE $t_bugnote_table.bug_id in (" . implode( ", ", $t_id_array_lastmod ) . ')';
  1795. $t_query = "SELECT DISTINCT bug_id,MAX(last_modified) as last_modified, COUNT(last_modified) as count FROM $t_bugnote_table $t_where_string GROUP BY bug_id";
  1796. # perform query
  1797. $t_result = db_query_bound( $t_query );
  1798. $t_row_count = db_num_rows( $t_result );
  1799. for( $i = 0;$i < $t_row_count;$i++ ) {
  1800. $t_row = db_fetch_array( $t_result );
  1801. $t_stats[$t_row['bug_id']] = $t_row;
  1802. }
  1803. $t_rows = array();
  1804. foreach( $p_rows as $t_row ) {
  1805. if( !isset( $t_stats[$t_row['id']] ) ) {
  1806. $t_rows[] = bug_row_to_object( bug_cache_database_result( $t_row, false ) );
  1807. } else {
  1808. $t_rows[] = bug_row_to_object( bug_cache_database_result( $t_row, $t_stats[ $t_row['id'] ] ) );
  1809. }
  1810. }
  1811. return $t_rows;
  1812. }
  1813. /**
  1814. * Mainly based on filter_draw_selection_area2() but adds the support for the collapsible
  1815. * filter display.
  1816. * @param int $p_page_number
  1817. * @param bool $p_for_screen
  1818. * @see filter_draw_selection_area2
  1819. */
  1820. function filter_draw_selection_area( $p_page_number, $p_for_screen = true ) {
  1821. collapse_open( 'filter' );
  1822. filter_draw_selection_area2( $p_page_number, $p_for_screen, true );
  1823. collapse_closed( 'filter' );
  1824. filter_draw_selection_area2( $p_page_number, $p_for_screen, false );
  1825. collapse_end( 'filter' );
  1826. }
  1827. /**
  1828. * Prints the filter selection area for both the bug list view screen and
  1829. * the bug list print screen. This function was an attempt to make it easier to
  1830. * add new filters and rearrange them on screen for both pages.
  1831. * @param int $p_page_number
  1832. * @param bool $p_for_screen
  1833. * @param bool $p_expanded
  1834. */
  1835. function filter_draw_selection_area2( $p_page_number, $p_for_screen = true, $p_expanded = true ) {
  1836. $t_form_name_suffix = $p_expanded ? '_open' : '_closed';
  1837. $t_filter = current_user_get_bug_filter();
  1838. $t_filter = filter_ensure_valid_filter( $t_filter );
  1839. $t_project_id = helper_get_current_project();
  1840. $t_page_number = (int) $p_page_number;
  1841. $t_view_type = $t_filter['_view_type'];
  1842. $t_tdclass = 'small-caption';
  1843. $t_trclass = 'row-category2';
  1844. $t_action = 'view_all_set.php?f=3';
  1845. if( $p_for_screen == false ) {
  1846. $t_tdclass = 'print';
  1847. $t_trclass = '';
  1848. $t_action = 'view_all_set.php';
  1849. }
  1850. ?>
  1851. <br />
  1852. <form method="post" name="filters<?php echo $t_form_name_suffix?>" id="filters_form<?php echo $t_form_name_suffix?>" action="<?php echo $t_action;?>">
  1853. <?php # CSRF protection not required here - form does not result in modifications ?>
  1854. <input type="hidden" name="type" value="1" />
  1855. <?php
  1856. if( $p_for_screen == false ) {
  1857. echo '<input type="hidden" name="print" value="1" />';
  1858. echo '<input type="hidden" name="offset" value="0" />';
  1859. }
  1860. ?>
  1861. <input type="hidden" name="page_number" value="<?php echo $t_page_number?>" />
  1862. <input type="hidden" name="view_type" value="<?php echo $t_view_type?>" />
  1863. <table class="width100" cellspacing="1">
  1864. <?php
  1865. $t_filter_cols = config_get( 'filter_custom_fields_per_row' );
  1866. if( $p_expanded ) {
  1867. $t_custom_cols = $t_filter_cols;
  1868. $t_current_user_access_level = current_user_get_access_level();
  1869. $t_accessible_custom_fields_ids = array();
  1870. $t_accessible_custom_fields_names = array();
  1871. $t_accessible_custom_fields_values = array();
  1872. $t_num_custom_rows = 0;
  1873. $t_per_row = 0;
  1874. if( ON == config_get( 'filter_by_custom_fields' ) ) {
  1875. $t_custom_fields = custom_field_get_linked_ids( $t_project_id );
  1876. foreach( $t_custom_fields as $t_cfid ) {
  1877. $t_field_info = custom_field_cache_row( $t_cfid, true );
  1878. if( $t_field_info['access_level_r'] <= $t_current_user_access_level && $t_field_info['filter_by'] ) {
  1879. $t_accessible_custom_fields_ids[] = $t_cfid;
  1880. $t_accessible_custom_fields_names[] = $t_field_info['name'];
  1881. $t_accessible_custom_fields_types[] = $t_field_info['type'];
  1882. $t_accessible_custom_fields_values[] = custom_field_distinct_values( $t_field_info );
  1883. }
  1884. }
  1885. if( count( $t_accessible_custom_fields_ids ) > 0 ) {
  1886. $t_per_row = config_get( 'filter_custom_fields_per_row' );
  1887. $t_num_custom_rows = ceil( count( $t_accessible_custom_fields_ids ) / $t_per_row );
  1888. }
  1889. }
  1890. $t_filters_url = 'view_filters_page.php?for_screen=' . $p_for_screen;
  1891. if( 'advanced' == $t_view_type ) {
  1892. $t_filters_url = $t_filters_url . '&amp;view_type=advanced';
  1893. }
  1894. $t_filters_url = $t_filters_url . '&amp;target_field=';
  1895. $t_show_product_version = version_should_show_product_version( $t_project_id );
  1896. $t_show_build = $t_show_product_version && ( config_get( 'enable_product_build' ) == ON );
  1897. # overload handler_id setting if user isn't supposed to see them (ref #6189)
  1898. if( !access_has_project_level( config_get( 'view_handler_threshold' ), $t_project_id ) ) {
  1899. $t_filter[FILTER_PROPERTY_HANDLER_ID] = array(
  1900. META_FILTER_ANY,
  1901. );
  1902. }
  1903. ?>
  1904. <tr <?php echo "class=\"" . $t_trclass . "\"";?>>
  1905. <td class="small-caption" valign="top">
  1906. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_REPORTER_ID . '[]';?>" id="reporter_id_filter"><?php echo lang_get( 'reporter_label' )?></a>
  1907. </td>
  1908. <td class="small-caption" valign="top">
  1909. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_MONITOR_USER_ID . '[]';?>" id="user_monitor_filter"><?php echo lang_get( 'monitored_by_label' )?></a>
  1910. </td>
  1911. <td class="small-caption" valign="top">
  1912. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_HANDLER_ID . '[]';?>" id="handler_id_filter"><?php echo lang_get( 'assigned_to_label' )?></a>
  1913. </td>
  1914. <td colspan="2" class="small-caption" valign="top">
  1915. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_CATEGORY_ID . '[]';?>" id="show_category_filter"><?php echo lang_get( 'category_label' )?></a>
  1916. </td>
  1917. <td class="small-caption" valign="top">
  1918. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_SEVERITY . '[]';?>" id="show_severity_filter"><?php echo lang_get( 'severity_label' )?></a>
  1919. </td>
  1920. <td class="small-caption" valign="top">
  1921. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_RESOLUTION . '[]';?>" id="show_resolution_filter"><?php echo lang_get( 'resolution_label' )?></a>
  1922. </td>
  1923. <td class="small-caption" valign="top">
  1924. <?php if( ON == config_get( 'enable_profiles' ) ) { ?>
  1925. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_PROFILE_ID . '[]';?>" id="show_profile_filter"><?php echo lang_get( 'profile_label' )?></a>
  1926. <?php } ?>
  1927. </td>
  1928. <?php if( $t_filter_cols > 8 ) {
  1929. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 8 ) . '">&nbsp;</td>';
  1930. }?>
  1931. </tr>
  1932. <tr class="row-1">
  1933. <td class="small-caption" valign="top" id="reporter_id_filter_target">
  1934. <?php
  1935. $t_output = '';
  1936. $t_any_found = false;
  1937. if( count( $t_filter[FILTER_PROPERTY_REPORTER_ID] ) == 0 ) {
  1938. echo lang_get( 'any' );
  1939. } else {
  1940. $t_first_flag = true;
  1941. foreach( $t_filter[FILTER_PROPERTY_REPORTER_ID] as $t_current ) {
  1942. $t_this_name = '';
  1943. echo '<input type="hidden" name="', FILTER_PROPERTY_REPORTER_ID, '[]" value="', $t_current, '" />';
  1944. if( filter_field_is_any( $t_current ) ) {
  1945. $t_any_found = true;
  1946. }
  1947. else if( filter_field_is_myself( $t_current ) ) {
  1948. if( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) {
  1949. $t_this_name = '[' . lang_get( 'myself' ) . ']';
  1950. } else {
  1951. $t_any_found = true;
  1952. }
  1953. } else if( filter_field_is_none( $t_current ) ) {
  1954. $t_this_name = lang_get( 'none' );
  1955. } else {
  1956. $t_this_name = user_get_name( $t_current );
  1957. }
  1958. if( $t_first_flag != true ) {
  1959. $t_output = $t_output . '<br />';
  1960. } else {
  1961. $t_first_flag = false;
  1962. }
  1963. $t_output = $t_output . $t_this_name;
  1964. }
  1965. if( true == $t_any_found ) {
  1966. echo lang_get( 'any' );
  1967. } else {
  1968. echo string_display( $t_output );
  1969. }
  1970. }
  1971. ?>
  1972. </td>
  1973. <td class="small-caption" valign="top" id="user_monitor_filter_target">
  1974. <?php
  1975. $t_output = '';
  1976. $t_any_found = false;
  1977. if( count( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID] ) == 0 ) {
  1978. echo lang_get( 'any' );
  1979. } else {
  1980. $t_first_flag = true;
  1981. foreach( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID] as $t_current ) {
  1982. echo '<input type="hidden" name="', FILTER_PROPERTY_MONITOR_USER_ID, '[]" value="', $t_current, '" />';
  1983. $t_this_name = '';
  1984. if( filter_field_is_any( $t_current ) ) {
  1985. $t_any_found = true;
  1986. }
  1987. else if( filter_field_is_myself( $t_current ) ) {
  1988. if( access_has_project_level( config_get( 'monitor_bug_threshold' ) ) ) {
  1989. $t_this_name = '[' . lang_get( 'myself' ) . ']';
  1990. } else {
  1991. $t_any_found = true;
  1992. }
  1993. } else {
  1994. $t_this_name = user_get_name( $t_current );
  1995. }
  1996. if( $t_first_flag != true ) {
  1997. $t_output = $t_output . '<br />';
  1998. } else {
  1999. $t_first_flag = false;
  2000. }
  2001. $t_output = $t_output . $t_this_name;
  2002. }
  2003. if( true == $t_any_found ) {
  2004. echo lang_get( 'any' );
  2005. } else {
  2006. echo string_display( $t_output );
  2007. }
  2008. }
  2009. ?>
  2010. </td>
  2011. <td class="small-caption" valign="top" id="handler_id_filter_target">
  2012. <?php
  2013. $t_output = '';
  2014. $t_any_found = false;
  2015. if( count( $t_filter[FILTER_PROPERTY_HANDLER_ID] ) == 0 ) {
  2016. echo lang_get( 'any' );
  2017. } else {
  2018. $t_first_flag = true;
  2019. foreach( $t_filter[FILTER_PROPERTY_HANDLER_ID] as $t_current ) {
  2020. echo '<input type="hidden" name="', FILTER_PROPERTY_HANDLER_ID, '[]" value="', $t_current, '" />';
  2021. $t_this_name = '';
  2022. if( filter_field_is_none( $t_current ) ) {
  2023. $t_this_name = lang_get( 'none' );
  2024. } else if( filter_field_is_any( $t_current ) ) {
  2025. $t_any_found = true;
  2026. } else if( filter_field_is_myself( $t_current ) ) {
  2027. if( access_has_project_level( config_get( 'handle_bug_threshold' ) ) ) {
  2028. $t_this_name = '[' . lang_get( 'myself' ) . ']';
  2029. } else {
  2030. $t_any_found = true;
  2031. }
  2032. } else {
  2033. $t_this_name = user_get_name( $t_current );
  2034. }
  2035. if( $t_first_flag != true ) {
  2036. $t_output = $t_output . '<br />';
  2037. } else {
  2038. $t_first_flag = false;
  2039. }
  2040. $t_output = $t_output . $t_this_name;
  2041. }
  2042. if( true == $t_any_found ) {
  2043. echo lang_get( 'any' );
  2044. } else {
  2045. echo string_display( $t_output );
  2046. }
  2047. }
  2048. ?>
  2049. </td>
  2050. <td colspan="2" class="small-caption" valign="top" id="show_category_filter_target">
  2051. <?php
  2052. $t_output = '';
  2053. $t_any_found = false;
  2054. if( count( $t_filter[FILTER_PROPERTY_CATEGORY_ID] ) == 0 ) {
  2055. echo lang_get( 'any' );
  2056. } else {
  2057. $t_first_flag = true;
  2058. foreach( $t_filter[FILTER_PROPERTY_CATEGORY_ID] as $t_current ) {
  2059. echo '<input type="hidden" name="', FILTER_PROPERTY_CATEGORY_ID, '[]" value="', $t_current, '" />';
  2060. $t_this_string = '';
  2061. if( filter_field_is_any( $t_current ) ) {
  2062. $t_any_found = true;
  2063. } else {
  2064. $t_this_string = string_display( $t_current );
  2065. }
  2066. if( $t_first_flag != true ) {
  2067. $t_output = $t_output . '<br />';
  2068. } else {
  2069. $t_first_flag = false;
  2070. }
  2071. $t_output = $t_output . $t_this_string;
  2072. }
  2073. if( true == $t_any_found ) {
  2074. echo lang_get( 'any' );
  2075. } else {
  2076. echo $t_output;
  2077. }
  2078. }
  2079. ?>
  2080. </td>
  2081. <td class="small-caption" valign="top" id="show_severity_filter_target">
  2082. <?php
  2083. $t_output = '';
  2084. $t_any_found = false;
  2085. if( count( $t_filter[FILTER_PROPERTY_SEVERITY] ) == 0 ) {
  2086. echo lang_get( 'any' );
  2087. } else {
  2088. $t_first_flag = true;
  2089. foreach( $t_filter[FILTER_PROPERTY_SEVERITY] as $t_current ) {
  2090. echo '<input type="hidden" name="', FILTER_PROPERTY_SEVERITY, '[]" value="', $t_current, '" />';
  2091. $t_this_string = '';
  2092. if( filter_field_is_any( $t_current ) ) {
  2093. $t_any_found = true;
  2094. } else {
  2095. $t_this_string = get_enum_element( 'severity', $t_current );
  2096. }
  2097. if( $t_first_flag != true ) {
  2098. $t_output = $t_output . '<br />';
  2099. } else {
  2100. $t_first_flag = false;
  2101. }
  2102. $t_output = $t_output . $t_this_string;
  2103. }
  2104. if( true == $t_any_found ) {
  2105. echo lang_get( 'any' );
  2106. } else {
  2107. echo $t_output;
  2108. }
  2109. }
  2110. ?>
  2111. </td>
  2112. <td class="small-caption" valign="top" id="show_resolution_filter_target">
  2113. <?php
  2114. $t_output = '';
  2115. $t_any_found = false;
  2116. if( count( $t_filter[FILTER_PROPERTY_RESOLUTION] ) == 0 ) {
  2117. echo lang_get( 'any' );
  2118. } else {
  2119. $t_first_flag = true;
  2120. foreach( $t_filter[FILTER_PROPERTY_RESOLUTION] as $t_current ) {
  2121. echo '<input type="hidden" name="', FILTER_PROPERTY_RESOLUTION, '[]" value="', $t_current, '" />';
  2122. $t_this_string = '';
  2123. if( filter_field_is_any( $t_current ) ) {
  2124. $t_any_found = true;
  2125. } else {
  2126. $t_this_string = get_enum_element( 'resolution', $t_current );
  2127. }
  2128. if( $t_first_flag != true ) {
  2129. $t_output = $t_output . '<br />';
  2130. } else {
  2131. $t_first_flag = false;
  2132. }
  2133. $t_output = $t_output . $t_this_string;
  2134. }
  2135. if( true == $t_any_found ) {
  2136. echo lang_get( 'any' );
  2137. } else {
  2138. echo $t_output;
  2139. }
  2140. }
  2141. ?>
  2142. </td>
  2143. <?php if( ON == config_get( 'enable_profiles' ) ) { ?>
  2144. <td class="small-caption" valign="top" id="show_profile_filter_target">
  2145. <?php
  2146. $t_output = '';
  2147. $t_any_found = false;
  2148. if( count( $t_filter[FILTER_PROPERTY_PROFILE_ID] ) == 0 ) {
  2149. echo lang_get( 'any' );
  2150. } else {
  2151. $t_first_flag = true;
  2152. foreach( $t_filter[FILTER_PROPERTY_PROFILE_ID] as $t_current ) {
  2153. echo '<input type="hidden" name="', FILTER_PROPERTY_PROFILE_ID, '[]" value="', $t_current, '" />';
  2154. $t_this_string = '';
  2155. if( filter_field_is_any( $t_current ) ) {
  2156. $t_any_found = true;
  2157. } else {
  2158. $t_profile = profile_get_row_direct( $t_current );
  2159. $t_this_string = "${t_profile['platform']} ${t_profile['os']} ${t_profile['os_build']}";
  2160. }
  2161. if( $t_first_flag != true ) {
  2162. $t_output = $t_output . '<br />';
  2163. } else {
  2164. $t_first_flag = false;
  2165. }
  2166. $t_output = $t_output . $t_this_string;
  2167. }
  2168. if( true == $t_any_found ) {
  2169. echo lang_get( 'any' );
  2170. } else {
  2171. echo $t_output;
  2172. }
  2173. }
  2174. ?>
  2175. </td>
  2176. <?php } else { ?>
  2177. <td></td>
  2178. <?php }
  2179. if( $t_filter_cols > 8 ) {
  2180. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 8 ) . '">&nbsp;</td>';
  2181. }?>
  2182. </tr>
  2183. <tr <?php echo "class=\"" . $t_trclass . "\"";?>>
  2184. <td class="small-caption" valign="top">
  2185. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_STATUS . '[]';?>" id="show_status_filter"><?php echo lang_get( 'status_label' )?></a>
  2186. </td>
  2187. <td class="small-caption" valign="top">
  2188. <?php if( 'simple' == $t_view_type ) {?>
  2189. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_HIDE_STATUS . '[]';?>" id="hide_status_filter"><?php echo lang_get( 'hide_status_label' )?></a>
  2190. <?php
  2191. }?>
  2192. </td>
  2193. <td class="small-caption" valign="top">
  2194. <?php if ( $t_show_build ) { ?>
  2195. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_BUILD . '[]';?>" id="show_build_filter"><?php echo lang_get( 'product_build_label' )?></a>
  2196. <?php } ?>
  2197. </td>
  2198. <?php if( $t_show_product_version ) {?>
  2199. <td colspan="2" class="small-caption" valign="top">
  2200. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_VERSION . '[]';?>" id="show_version_filter"><?php echo lang_get( 'product_version_label' )?></a>
  2201. </td>
  2202. <td colspan="1" class="small-caption" valign="top">
  2203. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_FIXED_IN_VERSION . '[]';?>" id="show_fixed_in_version_filter"><?php echo lang_get( 'fixed_in_version_label' )?></a>
  2204. </td>
  2205. <?php
  2206. } else {?>
  2207. <td colspan="2" class="small-caption" valign="top">
  2208. &nbsp;
  2209. </td>
  2210. <td colspan="1" class="small-caption" valign="top">
  2211. &nbsp;
  2212. </td>
  2213. <?php
  2214. }?>
  2215. <td colspan="1" class="small-caption" valign="top">
  2216. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_PRIORITY . '[]';?>" id="show_priority_filter"><?php echo lang_get( 'priority_label' )?></a>
  2217. </td>
  2218. <?php if( $t_show_product_version ) {?>
  2219. <td colspan="1" class="small-caption" valign="top">
  2220. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_TARGET_VERSION . '[]';?>" id="show_target_version_filter"><?php echo lang_get( 'target_version_label' )?></a>
  2221. </td>
  2222. <?php
  2223. } else {?>
  2224. <td colspan="1" class="small-caption" valign="top">
  2225. &nbsp;
  2226. </td>
  2227. <?php
  2228. }?>
  2229. <?php if( $t_filter_cols > 8 ) {
  2230. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 7 ) . '">&nbsp;</td>';
  2231. }?>
  2232. </tr>
  2233. <tr class="row-1">
  2234. <td class="small-caption" valign="top" id="show_status_filter_target">
  2235. <?php
  2236. $t_output = '';
  2237. $t_any_found = false;
  2238. if( count( $t_filter[FILTER_PROPERTY_STATUS] ) == 0 ) {
  2239. echo lang_get( 'any' );
  2240. } else {
  2241. $t_first_flag = true;
  2242. foreach( $t_filter[FILTER_PROPERTY_STATUS] as $t_current ) {
  2243. echo '<input type="hidden" name="', FILTER_PROPERTY_STATUS, '[]" value="', $t_current, '" />';
  2244. $t_this_string = '';
  2245. if( filter_field_is_any( $t_current ) ) {
  2246. $t_any_found = true;
  2247. } else {
  2248. $t_this_string = get_enum_element( 'status', $t_current );
  2249. }
  2250. if( $t_first_flag != true ) {
  2251. $t_output = $t_output . '<br />';
  2252. } else {
  2253. $t_first_flag = false;
  2254. }
  2255. $t_output = $t_output . $t_this_string;
  2256. }
  2257. if( true == $t_any_found ) {
  2258. echo lang_get( 'any' );
  2259. } else {
  2260. echo $t_output;
  2261. }
  2262. }
  2263. ?>
  2264. </td>
  2265. <td class="small-caption" valign="top" id="hide_status_filter_target">
  2266. <?php
  2267. if( 'simple' == $t_view_type ) {
  2268. $t_output = '';
  2269. $t_none_found = false;
  2270. if( count( $t_filter[FILTER_PROPERTY_HIDE_STATUS] ) == 0 ) {
  2271. echo lang_get( 'none' );
  2272. } else {
  2273. $t_first_flag = true;
  2274. foreach( $t_filter[FILTER_PROPERTY_HIDE_STATUS] as $t_current ) {
  2275. echo '<input type="hidden" name="', FILTER_PROPERTY_HIDE_STATUS, '[]" value="', $t_current, '" />';
  2276. $t_this_string = '';
  2277. if( filter_field_is_none( $t_current ) ) {
  2278. $t_none_found = true;
  2279. } else {
  2280. $t_this_string = get_enum_element( 'status', $t_current );
  2281. }
  2282. if( $t_first_flag != true ) {
  2283. $t_output = $t_output . '<br />';
  2284. } else {
  2285. $t_first_flag = false;
  2286. }
  2287. $t_output = $t_output . $t_this_string;
  2288. }
  2289. $t_hide_status_post = '';
  2290. if( count( $t_filter[FILTER_PROPERTY_HIDE_STATUS] ) == 1 ) {
  2291. $t_hide_status_post = ' (' . lang_get( 'and_above' ) . ')';
  2292. }
  2293. if( true == $t_none_found ) {
  2294. echo lang_get( 'none' );
  2295. } else {
  2296. echo $t_output . $t_hide_status_post;
  2297. }
  2298. }
  2299. }
  2300. ?>
  2301. </td>
  2302. <?php if ( $t_show_build ) { ?>
  2303. <td class="small-caption" valign="top" id="show_build_filter_target">
  2304. <?php
  2305. $t_output = '';
  2306. $t_any_found = false;
  2307. if( count( $t_filter[FILTER_PROPERTY_BUILD] ) == 0 ) {
  2308. echo lang_get( 'any' );
  2309. } else {
  2310. $t_first_flag = true;
  2311. foreach( $t_filter[FILTER_PROPERTY_BUILD] as $t_current ) {
  2312. $t_current = stripslashes( $t_current );
  2313. echo '<input type="hidden" name="', FILTER_PROPERTY_BUILD, '[]" value="', string_display( $t_current ), '" />';
  2314. $t_this_string = '';
  2315. if( filter_field_is_any( $t_current ) ) {
  2316. $t_any_found = true;
  2317. } else if( filter_field_is_none( $t_current ) ) {
  2318. $t_this_string = lang_get( 'none' );
  2319. } else {
  2320. $t_this_string = string_display( $t_current );
  2321. }
  2322. if( $t_first_flag != true ) {
  2323. $t_output = $t_output . '<br />';
  2324. } else {
  2325. $t_first_flag = false;
  2326. }
  2327. $t_output = $t_output . $t_this_string;
  2328. }
  2329. if( true == $t_any_found ) {
  2330. echo lang_get( 'any' );
  2331. } else {
  2332. echo $t_output;
  2333. }
  2334. }
  2335. ?>
  2336. </td>
  2337. <?php } else { ?>
  2338. <td class="small-caption" valign="top"></td>
  2339. <?php }
  2340. if( $t_show_product_version ) {
  2341. ?>
  2342. <td colspan="2" class="small-caption" valign="top" id="show_version_filter_target">
  2343. <?php
  2344. $t_output = '';
  2345. $t_any_found = false;
  2346. if( count( $t_filter[FILTER_PROPERTY_VERSION] ) == 0 ) {
  2347. echo lang_get( 'any' );
  2348. } else {
  2349. $t_first_flag = true;
  2350. foreach( $t_filter[FILTER_PROPERTY_VERSION] as $t_current ) {
  2351. $t_current = stripslashes( $t_current );
  2352. echo '<input type="hidden" name="', FILTER_PROPERTY_VERSION, '[]" value="', string_display( $t_current ), '" />';
  2353. $t_this_string = '';
  2354. if( filter_field_is_any( $t_current ) ) {
  2355. $t_any_found = true;
  2356. }
  2357. else if( filter_field_is_none( $t_current ) ) {
  2358. $t_this_string = lang_get( 'none' );
  2359. } else {
  2360. $t_this_string = string_display( $t_current );
  2361. }
  2362. if( $t_first_flag != true ) {
  2363. $t_output = $t_output . '<br />';
  2364. } else {
  2365. $t_first_flag = false;
  2366. }
  2367. $t_output = $t_output . $t_this_string;
  2368. }
  2369. if( true == $t_any_found ) {
  2370. echo lang_get( 'any' );
  2371. } else {
  2372. echo $t_output;
  2373. }
  2374. }
  2375. ?>
  2376. </td>
  2377. <td colspan="1" class="small-caption" valign="top" id="show_fixed_in_version_filter_target">
  2378. <?php
  2379. $t_output = '';
  2380. $t_any_found = false;
  2381. if( count( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION] ) == 0 ) {
  2382. echo lang_get( 'any' );
  2383. } else {
  2384. $t_first_flag = true;
  2385. foreach( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION] as $t_current ) {
  2386. $t_current = stripslashes( $t_current );
  2387. echo '<input type="hidden" name="', FILTER_PROPERTY_FIXED_IN_VERSION, '[]" value="', string_display( $t_current ), '" />';
  2388. $t_this_string = '';
  2389. if( filter_field_is_any( $t_current ) ) {
  2390. $t_any_found = true;
  2391. } else if( filter_field_is_none( $t_current ) ) {
  2392. $t_this_string = lang_get( 'none' );
  2393. } else {
  2394. $t_this_string = string_display( $t_current );
  2395. }
  2396. if( $t_first_flag != true ) {
  2397. $t_output = $t_output . '<br />';
  2398. } else {
  2399. $t_first_flag = false;
  2400. }
  2401. $t_output = $t_output . $t_this_string;
  2402. }
  2403. if( true == $t_any_found ) {
  2404. echo lang_get( 'any' );
  2405. } else {
  2406. echo $t_output;
  2407. }
  2408. }
  2409. ?>
  2410. </td>
  2411. <?php
  2412. } else {?>
  2413. <td colspan="2" class="small-caption" valign="top">
  2414. &nbsp;
  2415. </td>
  2416. <td colspan="1" class="small-caption" valign="top">
  2417. &nbsp;
  2418. </td>
  2419. <?php
  2420. }?>
  2421. <td colspan="1" class="small-caption" valign="top" id="show_priority_filter_target">
  2422. <?php
  2423. $t_output = '';
  2424. $t_any_found = false;
  2425. if( count( $t_filter[FILTER_PROPERTY_PRIORITY] ) == 0 ) {
  2426. echo lang_get( 'any' );
  2427. } else {
  2428. $t_first_flag = true;
  2429. foreach( $t_filter[FILTER_PROPERTY_PRIORITY] as $t_current ) {
  2430. echo '<input type="hidden" name="', FILTER_PROPERTY_PRIORITY, '[]" value="', $t_current, '" />';
  2431. $t_this_string = '';
  2432. if( filter_field_is_any( $t_current ) ) {
  2433. $t_any_found = true;
  2434. } else {
  2435. $t_this_string = get_enum_element( 'priority', $t_current );
  2436. }
  2437. if( $t_first_flag != true ) {
  2438. $t_output = $t_output . '<br />';
  2439. } else {
  2440. $t_first_flag = false;
  2441. }
  2442. $t_output = $t_output . $t_this_string;
  2443. }
  2444. if( true == $t_any_found ) {
  2445. echo lang_get( 'any' );
  2446. } else {
  2447. echo $t_output;
  2448. }
  2449. }
  2450. ?>
  2451. </td>
  2452. <?php if( $t_show_product_version ) { ?>
  2453. <td colspan="1" class="small-caption" valign="top" id="show_target_version_filter_target">
  2454. <?php
  2455. $t_output = '';
  2456. $t_any_found = false;
  2457. if( count( $t_filter[FILTER_PROPERTY_TARGET_VERSION] ) == 0 ) {
  2458. echo lang_get( 'any' );
  2459. } else {
  2460. $t_first_flag = true;
  2461. foreach( $t_filter[FILTER_PROPERTY_TARGET_VERSION] as $t_current ) {
  2462. $t_current = stripslashes( $t_current );
  2463. echo '<input type="hidden" name="', FILTER_PROPERTY_TARGET_VERSION, '[]" value="', string_display( $t_current ), '" />';
  2464. $t_this_string = '';
  2465. if( filter_field_is_any( $t_current ) ) {
  2466. $t_any_found = true;
  2467. } else if( filter_field_is_none( $t_current ) ) {
  2468. $t_this_string = lang_get( 'none' );
  2469. } else {
  2470. $t_this_string = string_display( $t_current );
  2471. }
  2472. if( $t_first_flag != true ) {
  2473. $t_output = $t_output . '<br />';
  2474. } else {
  2475. $t_first_flag = false;
  2476. }
  2477. $t_output = $t_output . $t_this_string;
  2478. }
  2479. if( true == $t_any_found ) {
  2480. echo lang_get( 'any' );
  2481. } else {
  2482. echo $t_output;
  2483. }
  2484. }
  2485. ?>
  2486. </td>
  2487. <?php } else { ?>
  2488. <td colspan="1" class="small-caption" valign="top">
  2489. &nbsp;
  2490. </td>
  2491. <?php }
  2492. if( $t_filter_cols > 8 ) {
  2493. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 7 ) . '">&nbsp;</td>';
  2494. }?>
  2495. </tr>
  2496. <tr <?php echo "class=\"" . $t_trclass . "\"";?>>
  2497. <td class="small-caption" valign="top">
  2498. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_ISSUES_PER_PAGE;?>" id="per_page_filter"><?php echo lang_get( 'show_label' )?></a>
  2499. </td>
  2500. <td class="small-caption" valign="top">
  2501. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_VIEW_STATE;?>" id="view_state_filter"><?php echo lang_get( 'view_status_label' )?></a>
  2502. </td>
  2503. <td class="small-caption" valign="top">
  2504. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_STICKY;?>" id="sticky_issues_filter"><?php echo lang_get( 'sticky_label' )?></a>
  2505. </td>
  2506. <td class="small-caption" valign="top" colspan="2">
  2507. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_HIGHLIGHT_CHANGED;?>" id="highlight_changed_filter"><?php echo lang_get( 'changed_label' )?></a>
  2508. </td>
  2509. <td class="small-caption" valign="top" >
  2510. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_FILTER_BY_DATE;?>" id="do_filter_by_date_filter"><?php echo lang_get( 'use_date_filters_label' )?></a>
  2511. </td>
  2512. <td class="small-caption" valign="top" colspan="2">
  2513. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_RELATIONSHIP_TYPE;?>" id="relationship_type_filter"><?php echo lang_get( 'bug_relationships_label' )?></a>
  2514. </td>
  2515. <?php if( $t_filter_cols > 8 ) {
  2516. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 8 ) . '">&nbsp;</td>';
  2517. }?>
  2518. </tr>
  2519. <tr class="row-1">
  2520. <td class="small-caption" valign="top" id="per_page_filter_target">
  2521. <?php
  2522. echo( $t_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] == 0 ) ? lang_get( 'all' ) : $t_filter[FILTER_PROPERTY_ISSUES_PER_PAGE];
  2523. echo '<input type="hidden" name="', FILTER_PROPERTY_ISSUES_PER_PAGE, '" value="', $t_filter[FILTER_PROPERTY_ISSUES_PER_PAGE], '" />';
  2524. ?>
  2525. </td>
  2526. <td class="small-caption" valign="top" id="view_state_filter_target">
  2527. <?php
  2528. if( VS_PUBLIC === $t_filter[FILTER_PROPERTY_VIEW_STATE] ) {
  2529. echo lang_get( 'public' );
  2530. } else if( VS_PRIVATE === $t_filter[FILTER_PROPERTY_VIEW_STATE] ) {
  2531. echo lang_get( 'private' );
  2532. } else {
  2533. echo lang_get( 'any' );
  2534. $t_filter[FILTER_PROPERTY_VIEW_STATE] = META_FILTER_ANY;
  2535. }
  2536. echo '<input type="hidden" name="', FILTER_PROPERTY_VIEW_STATE, '" value="', $t_filter[FILTER_PROPERTY_VIEW_STATE], '" />';
  2537. ?>
  2538. </td>
  2539. <td class="small-caption" valign="top" id="sticky_issues_filter_target">
  2540. <?php
  2541. $t_sticky_filter_state = gpc_string_to_bool( $t_filter[FILTER_PROPERTY_STICKY] );
  2542. print( $t_sticky_filter_state ? lang_get( 'yes' ) : lang_get( 'no' ) );
  2543. ?>
  2544. <input type="hidden" name="sticky_issues" value="<?php echo $t_sticky_filter_state ? 'on' : 'off';?>" />
  2545. </td>
  2546. <td class="small-caption" valign="top" colspan="2" id="highlight_changed_filter_target">
  2547. <?php
  2548. echo $t_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED];
  2549. echo '<input type="hidden" name="', FILTER_PROPERTY_HIGHLIGHT_CHANGED, '" value="', $t_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED], '" />';
  2550. ?>
  2551. </td>
  2552. <td class="small-caption" valign="top" id="do_filter_by_date_filter_target">
  2553. <?php
  2554. if(( ON == config_get( 'dhtml_filters' ) ) && ( ON == config_get( 'use_javascript' ) ) ) {
  2555. ?>
  2556. <script type="text/javascript">
  2557. <!--
  2558. function SwitchDateFields() {
  2559. // All fields need to be enabled to go back to the script
  2560. document.filters_open.start_month.disabled = ! document.filters_open.filter_by_date.checked;
  2561. document.filters_open.start_day.disabled = ! document.filters_open.filter_by_date.checked;
  2562. document.filters_open.start_year.disabled = ! document.filters_open.filter_by_date.checked;
  2563. document.filters_open.end_month.disabled = ! document.filters_open.filter_by_date.checked;
  2564. document.filters_open.end_day.disabled = ! document.filters_open.filter_by_date.checked;
  2565. document.filters_open.end_year.disabled = ! document.filters_open.filter_by_date.checked;
  2566. return true;
  2567. }
  2568. // -->
  2569. </script>
  2570. <?php
  2571. }
  2572. # end if dhtml_filters
  2573. if( 'on' == $t_filter[FILTER_PROPERTY_FILTER_BY_DATE] ) {
  2574. echo '<input type="hidden" name="', FILTER_PROPERTY_FILTER_BY_DATE, '" value="', $t_filter[FILTER_PROPERTY_FILTER_BY_DATE], '" />';
  2575. echo '<input type="hidden" name="', FILTER_PROPERTY_START_MONTH, '" value="', $t_filter[FILTER_PROPERTY_START_MONTH], '" />';
  2576. echo '<input type="hidden" name="', FILTER_PROPERTY_START_DAY, '" value="', $t_filter[FILTER_PROPERTY_START_DAY], '" />';
  2577. echo '<input type="hidden" name="', FILTER_PROPERTY_START_YEAR, '" value="', $t_filter[FILTER_PROPERTY_START_YEAR], '" />';
  2578. echo '<input type="hidden" name="', FILTER_PROPERTY_END_MONTH, '" value="', $t_filter[FILTER_PROPERTY_END_MONTH], '" />';
  2579. echo '<input type="hidden" name="', FILTER_PROPERTY_END_DAY, '" value="', $t_filter[FILTER_PROPERTY_END_DAY], '" />';
  2580. echo '<input type="hidden" name="', FILTER_PROPERTY_END_YEAR, '" value="', $t_filter[FILTER_PROPERTY_END_YEAR], '" />';
  2581. $t_chars = preg_split( '//', config_get( 'short_date_format' ), -1, PREG_SPLIT_NO_EMPTY );
  2582. $t_time = mktime( 0, 0, 0, $t_filter[FILTER_PROPERTY_START_MONTH], $t_filter[FILTER_PROPERTY_START_DAY], $t_filter[FILTER_PROPERTY_START_YEAR] );
  2583. foreach( $t_chars as $t_char ) {
  2584. if( strcasecmp( $t_char, "M" ) == 0 ) {
  2585. echo ' ';
  2586. echo date( 'F', $t_time );
  2587. }
  2588. if( strcasecmp( $t_char, "D" ) == 0 ) {
  2589. echo ' ';
  2590. echo date( 'd', $t_time );
  2591. }
  2592. if( strcasecmp( $t_char, "Y" ) == 0 ) {
  2593. echo ' ';
  2594. echo date( 'Y', $t_time );
  2595. }
  2596. }
  2597. echo ' - ';
  2598. $t_time = mktime( 0, 0, 0, $t_filter[FILTER_PROPERTY_END_MONTH], $t_filter[FILTER_PROPERTY_END_DAY], $t_filter[FILTER_PROPERTY_END_YEAR] );
  2599. foreach( $t_chars as $t_char ) {
  2600. if( strcasecmp( $t_char, "M" ) == 0 ) {
  2601. echo ' ';
  2602. echo date( 'F', $t_time );
  2603. }
  2604. if( strcasecmp( $t_char, "D" ) == 0 ) {
  2605. echo ' ';
  2606. echo date( 'd', $t_time );
  2607. }
  2608. if( strcasecmp( $t_char, "Y" ) == 0 ) {
  2609. echo ' ';
  2610. echo date( 'Y', $t_time );
  2611. }
  2612. }
  2613. } else {
  2614. echo lang_get( 'no' );
  2615. }
  2616. ?>
  2617. </td>
  2618. <td class="small-caption" valign="top" colspan="2" id="relationship_type_filter_target">
  2619. <?php
  2620. echo '<input type="hidden" name="', FILTER_PROPERTY_RELATIONSHIP_TYPE, '" value="', $t_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE], '" />';
  2621. echo '<input type="hidden" name="', FILTER_PROPERTY_RELATIONSHIP_BUG, '" value="', $t_filter[FILTER_PROPERTY_RELATIONSHIP_BUG], '" />';
  2622. $c_rel_type = $t_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE];
  2623. $c_rel_bug = $t_filter[FILTER_PROPERTY_RELATIONSHIP_BUG];
  2624. if( -1 == $c_rel_type || 0 == $c_rel_bug ) {
  2625. echo lang_get( 'any' );
  2626. } else {
  2627. echo relationship_get_description_for_history( $c_rel_type ) . ' ' . $c_rel_bug;
  2628. }
  2629. ?>
  2630. </td>
  2631. <?php if( $t_filter_cols > 8 ) {
  2632. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 8 ) . '">&nbsp;</td>';
  2633. }?>
  2634. </tr>
  2635. <tr <?php echo "class=\"" . $t_trclass . "\"";?>>
  2636. <td class="small-caption" valign="top">
  2637. <?php if( ON == config_get( 'enable_profiles' ) ) { ?>
  2638. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_PLATFORM;?>" id="platform_filter"><?php echo lang_get( 'platform_label' )?></a>
  2639. <?php } ?>
  2640. </td>
  2641. <td class="small-caption" valign="top">
  2642. <?php if( ON == config_get( 'enable_profiles' ) ) { ?>
  2643. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_OS;?>" id="os_filter"><?php echo lang_get( 'os_label' )?></a>
  2644. <?php } ?>
  2645. </td>
  2646. <td class="small-caption" valign="top">
  2647. <?php if( ON == config_get( 'enable_profiles' ) ) { ?>
  2648. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_OS_BUILD;?>" id="os_build_filter"><?php echo lang_get( 'os_version_label' )?></a>
  2649. <?php } ?>
  2650. </td>
  2651. <td class="small-caption" valign="top" colspan="5">
  2652. <?php if ( access_has_global_level( config_get( 'tag_view_threshold' ) ) ) { ?>
  2653. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_TAG_STRING;?>" id="tag_string_filter"><?php echo lang_get( 'tags_label' )?></a>
  2654. <?php } ?>
  2655. </td>
  2656. <?php if( $t_filter_cols > 8 ) {
  2657. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 8 ) . '">&nbsp;</td>';
  2658. }?>
  2659. </tr>
  2660. <tr class="row-1">
  2661. <?php if( ON == config_get( 'enable_profiles' ) ) { ?>
  2662. <td class="small-caption" valign="top" id="platform_filter_target">
  2663. <?php
  2664. print_multivalue_field( FILTER_PROPERTY_PLATFORM, $t_filter[FILTER_PROPERTY_PLATFORM] );
  2665. ?>
  2666. </td>
  2667. <td class="small-caption" valign="top" id="os_filter_target">
  2668. <?php
  2669. print_multivalue_field( FILTER_PROPERTY_OS, $t_filter[FILTER_PROPERTY_OS] );
  2670. ?>
  2671. </td>
  2672. <td class="small-caption" valign="top" id="os_build_filter_target">
  2673. <?php
  2674. print_multivalue_field( FILTER_PROPERTY_OS_BUILD, $t_filter[FILTER_PROPERTY_OS_BUILD] );
  2675. ?>
  2676. </td>
  2677. <?php } else {?>
  2678. <td colspan="3">&nbsp;</td>
  2679. <?php } ?>
  2680. <td class="small-caption" valign="top" id="tag_string_filter_target" colspan="5">
  2681. <?php
  2682. $t_tag_string = $t_filter[FILTER_PROPERTY_TAG_STRING];
  2683. if( $t_filter[FILTER_PROPERTY_TAG_SELECT] != 0 && tag_exists( $t_filter[FILTER_PROPERTY_TAG_SELECT] ) ) {
  2684. $t_tag_string .= ( is_blank( $t_tag_string ) ? '' : config_get( 'tag_separator' ) );
  2685. $t_tag_string .= tag_get_field( $t_filter[FILTER_PROPERTY_TAG_SELECT], 'name' );
  2686. }
  2687. echo string_html_entities( $t_tag_string );
  2688. echo '<input type="hidden" name="', FILTER_PROPERTY_TAG_STRING, '" value="', string_attribute( $t_tag_string ), '" />';
  2689. ?>
  2690. </td>
  2691. </tr>
  2692. <?php
  2693. # get plugin filters
  2694. $t_plugin_filters = filter_get_plugin_filters();
  2695. $t_column = 0;
  2696. $t_fields = '';
  2697. $t_values = '';
  2698. # output a filter form element for each plugin filter
  2699. foreach( $t_plugin_filters as $t_field_name => $t_filter_object ) {
  2700. $t_fields .= '<td class="small-caption" valign="top"> <a href="' . $t_filters_url . $t_field_name .
  2701. '" id="' . $t_field_name . '_filter">' . string_display_line( $t_filter_object->title ) . '</a> </td>';
  2702. $t_values .= '<td class="small-caption" valign="top" id="' . $t_field_name . '_filter_target"> ';
  2703. if ( !isset( $t_filter[ $t_field_name ] ) ) {
  2704. $t_values .= lang_get( 'any' );
  2705. } else {
  2706. switch( $t_filter_object->type ) {
  2707. case FILTER_TYPE_STRING:
  2708. case FILTER_TYPE_INT:
  2709. if ( filter_field_is_any( $t_filter[ $t_field_name ] ) ) {
  2710. $t_values .= lang_get( 'any' );
  2711. } else {
  2712. $t_values .= string_display( $t_filter[ $t_field_name ] );
  2713. }
  2714. $t_values .= '<input type="hidden" name="' . string_attribute( $t_field_name ) . '" value="' . string_attribute( $t_filter[ $t_field_name ] ) . '"/>';
  2715. break;
  2716. case FILTER_TYPE_BOOLEAN:
  2717. $t_values .= string_display( $t_filter_object->display( (bool)$t_filter[ $t_field_name ] ) );
  2718. $t_values .= '<input type="hidden" name="' . string_attribute( $t_field_name ) . '" value="' . (bool)$t_filter[ $t_field_name ] . '"/>';
  2719. break;
  2720. case FILTER_TYPE_MULTI_STRING:
  2721. case FILTER_TYPE_MULTI_INT:
  2722. $t_first = true;
  2723. $t_output = '';
  2724. if ( !is_array( $t_filter[ $t_field_name ] ) ) {
  2725. $t_filter[ $t_field_name ] = array( $t_filter[ $t_field_name ] );
  2726. }
  2727. foreach( $t_filter[ $t_field_name ] as $t_current ) {
  2728. if ( filter_field_is_any( $t_current ) ) {
  2729. $t_output .= lang_get( 'any' );
  2730. } else {
  2731. $t_output .= ( $t_first ? '' : '<br/>' ) . string_display( $t_filter_object->display( $t_current ) );
  2732. $t_first = false;
  2733. }
  2734. $t_values .= '<input type="hidden" name="' . string_attribute( $t_field_name ) . '[]" value="' . string_attribute( $t_current ) . '"/>';
  2735. }
  2736. $t_values .= $t_output;
  2737. break;
  2738. }
  2739. }
  2740. $t_values .= '</td>';
  2741. $t_column++;
  2742. # wrap at the appropriate column
  2743. if ( $t_column >= $t_filter_cols ) {
  2744. echo '<tr class="', $t_trclass, '">', $t_fields, '</tr>';
  2745. echo '<tr class="row-1">', $t_values, '</tr>';
  2746. $t_fields = '';
  2747. $t_values = '';
  2748. }
  2749. }
  2750. # output any remaining plugin filters
  2751. if ( $t_column > 0 ) {
  2752. if ( $t_column < $t_filter_cols ) {
  2753. $t_fields .= '<td class="small-caption" colspan="' . ( $t_filter_cols - $t_column ) . '">&nbsp;</td>';
  2754. $t_values .= '<td class="small-caption" colspan="' . ( $t_filter_cols - $t_column ) . '">&nbsp;</td>';
  2755. }
  2756. echo '<tr class="', $t_trclass, '">', $t_fields, '</tr>';
  2757. echo '<tr class="row-1">', $t_values, '</tr>';
  2758. }
  2759. if( ON == config_get( 'filter_by_custom_fields' ) ) {
  2760. # -- Custom Field Searching --
  2761. if( count( $t_accessible_custom_fields_ids ) > 0 ) {
  2762. $t_per_row = config_get( 'filter_custom_fields_per_row' );
  2763. $t_num_fields = count( $t_accessible_custom_fields_ids );
  2764. $t_row_idx = 0;
  2765. $t_col_idx = 0;
  2766. $t_fields = '';
  2767. $t_values = '';
  2768. for( $i = 0;$i < $t_num_fields;$i++ ) {
  2769. if( $t_col_idx == 0 ) {
  2770. $t_fields = '<tr class="' . $t_trclass . '">';
  2771. $t_values = '<tr class="row-1">';
  2772. }
  2773. if( isset( $t_accessible_custom_fields_names[$i] ) ) {
  2774. $t_fields .= '<td class="small-caption" valign="top"> ';
  2775. $t_fields .= '<a href="' . $t_filters_url . 'custom_field_' . $t_accessible_custom_fields_ids[$i] . '[]" id="custom_field_' . $t_accessible_custom_fields_ids[$i] . '_filter">';
  2776. $t_fields .= string_display( lang_get_defaulted( $t_accessible_custom_fields_names[$i] ) );
  2777. $t_fields .= '</a> </td> ';
  2778. }
  2779. $t_output = '';
  2780. $t_any_found = false;
  2781. $t_values .= '<td class="small-caption" valign="top" id="custom_field_' . $t_accessible_custom_fields_ids[$i] . '_filter_target"> ';
  2782. if( !isset( $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]] ) ) {
  2783. $t_values .= lang_get( 'any' );
  2784. } else {
  2785. if( $t_accessible_custom_fields_types[$i] == CUSTOM_FIELD_TYPE_DATE ) {
  2786. /** @todo moved embedded javascript here from print_filter_custom_field_date
  2787. * it appears not to load properly on Firefox and other browsers if loaded through the httpxmlreq
  2788. */
  2789. $t_field_id = $t_accessible_custom_fields_ids[$i];
  2790. $t_js_toggle_func = "toggle_custom_date_field_" . $t_field_id . "_controls";
  2791. if(( ON == config_get( 'dhtml_filters' ) ) && ( ON == config_get( 'use_javascript' ) ) ) {
  2792. ?>
  2793. <script type="text/javascript">
  2794. <!--
  2795. function <?php echo $t_js_toggle_func . "_start";?>(disable) {
  2796. document.filters_open.custom_field_<?php echo $t_field_id;?>_start_year.disabled = disable ;
  2797. document.filters_open.custom_field_<?php echo $t_field_id;?>_start_month.disabled = disable ;
  2798. document.filters_open.custom_field_<?php echo $t_field_id;?>_start_day.disabled = disable ;
  2799. } ;
  2800. function <?php echo $t_js_toggle_func . "_end";?>(disable) {
  2801. document.filters_open.custom_field_<?php echo $t_field_id;?>_end_year.disabled = disable ;
  2802. document.filters_open.custom_field_<?php echo $t_field_id;?>_end_month.disabled = disable ;
  2803. document.filters_open.custom_field_<?php echo $t_field_id;?>_end_day.disabled = disable ;
  2804. } ;
  2805. function <?php echo $t_js_toggle_func;?>() {
  2806. switch (document.filters_open.custom_field_<?php echo $t_field_id;?>_control.selectedIndex) {
  2807. case <?php echo CUSTOM_FIELD_DATE_ANY;?>:
  2808. case <?php echo CUSTOM_FIELD_DATE_NONE;?>:
  2809. <?php echo $t_js_toggle_func . "_start";?>(true) ;
  2810. <?php echo $t_js_toggle_func . "_end";?>(true) ;
  2811. break ;
  2812. case <?php echo CUSTOM_FIELD_DATE_BETWEEN;?>:
  2813. <?php echo $t_js_toggle_func . "_start";?>(false) ;
  2814. <?php echo $t_js_toggle_func . "_end";?>(false) ;
  2815. break ;
  2816. default:
  2817. <?php echo $t_js_toggle_func . "_start";?>(false) ;
  2818. <?php echo $t_js_toggle_func . "_end";?>(true) ;
  2819. break ;
  2820. }
  2821. }
  2822. // -->
  2823. </script>
  2824. <?php
  2825. }
  2826. # end if dhtml_filters
  2827. $t_short_date_format = config_get( 'short_date_format' );
  2828. if( !isset( $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]][1] ) ) {
  2829. $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]][1] = 0;
  2830. }
  2831. $t_start = date( $t_short_date_format, $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]][1] );
  2832. if( !isset( $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]][2] ) ) {
  2833. $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]][2] = 0;
  2834. }
  2835. $t_end = date( $t_short_date_format, $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]][2] );
  2836. switch( $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]][0] ) {
  2837. case CUSTOM_FIELD_DATE_ANY:
  2838. $t_values .= lang_get( 'any' );
  2839. break;
  2840. case CUSTOM_FIELD_DATE_NONE:
  2841. $t_values .= lang_get( 'none' );
  2842. break;
  2843. case CUSTOM_FIELD_DATE_BETWEEN:
  2844. $t_values .= lang_get( 'between_date' ) . '<br />';
  2845. $t_values .= $t_start . '<br />' . $t_end;
  2846. break;
  2847. case CUSTOM_FIELD_DATE_ONORBEFORE:
  2848. $t_values .= lang_get( 'on_or_before_date' ) . '<br />';
  2849. $t_values .= $t_end;
  2850. break;
  2851. case CUSTOM_FIELD_DATE_BEFORE:
  2852. $t_values .= lang_get( 'before_date' ) . '<br />';
  2853. $t_values .= $t_end;
  2854. break;
  2855. case CUSTOM_FIELD_DATE_ON:
  2856. $t_values .= lang_get( 'on_date' ) . '<br />';
  2857. $t_values .= $t_start;
  2858. break;
  2859. case CUSTOM_FIELD_DATE_AFTER:
  2860. $t_values .= lang_get( 'after_date' ) . '<br />';
  2861. $t_values .= $t_start;
  2862. break;
  2863. case CUSTOM_FIELD_DATE_ONORAFTER:
  2864. $t_values .= lang_get( 'on_or_after_date' ) . '<br />';
  2865. $t_values .= $t_start;
  2866. break;
  2867. }
  2868. } else {
  2869. $t_first_flag = true;
  2870. foreach( $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]] as $t_current ) {
  2871. $t_current = stripslashes( $t_current );
  2872. $t_this_string = '';
  2873. if( filter_field_is_any( $t_current ) ) {
  2874. $t_any_found = true;
  2875. } else if( filter_field_is_none( $t_current ) ) {
  2876. $t_this_string = lang_get( 'none' );
  2877. } else {
  2878. $t_this_string = string_display( $t_current );
  2879. }
  2880. if( $t_first_flag != true ) {
  2881. $t_output = $t_output . '<br />';
  2882. } else {
  2883. $t_first_flag = false;
  2884. }
  2885. $t_output = $t_output . $t_this_string;
  2886. $t_values .= '<input type="hidden" name="custom_field_' . $t_accessible_custom_fields_ids[$i] . '[]" value="' . string_display( $t_current ) . '" />';
  2887. }
  2888. }
  2889. if( true == $t_any_found ) {
  2890. $t_values .= lang_get( 'any' );
  2891. } else {
  2892. $t_values .= $t_output;
  2893. }
  2894. }
  2895. $t_values .= ' </td>';
  2896. $t_col_idx++;
  2897. if( $t_col_idx == $t_per_row ) {
  2898. if( $t_filter_cols > $t_per_row ) {
  2899. $t_fields .= '<td colspan="' . ( $t_filter_cols - $t_per_row ) . '">&nbsp;</td> ';
  2900. $t_values .= '<td colspan="' . ( $t_filter_cols - $t_per_row ) . '">&nbsp;</td> ';
  2901. }
  2902. $t_fields .= '</tr>' . "\n";
  2903. $t_values .= '</tr>' . "\n";
  2904. echo $t_fields;
  2905. echo $t_values;
  2906. $t_col_idx = 0;
  2907. $t_row_idx++;
  2908. }
  2909. }
  2910. if( $t_col_idx > 0 ) {
  2911. if( $t_col_idx < $t_per_row ) {
  2912. $t_fields .= '<td colspan="' . ( $t_per_row - $t_col_idx ) . '">&nbsp;</td> ';
  2913. $t_values .= '<td colspan="' . ( $t_per_row - $t_col_idx ) . '">&nbsp;</td> ';
  2914. }
  2915. if( $t_filter_cols > $t_per_row ) {
  2916. $t_fields .= '<td colspan="' . ( $t_filter_cols - $t_per_row ) . '">&nbsp;</td> ';
  2917. $t_values .= '<td colspan="' . ( $t_filter_cols - $t_per_row ) . '">&nbsp;</td> ';
  2918. }
  2919. $t_fields .= '</tr>' . "\n";
  2920. $t_values .= '</tr>' . "\n";
  2921. echo $t_fields;
  2922. echo $t_values;
  2923. }
  2924. }
  2925. }
  2926. ?>
  2927. <tr class="row-1">
  2928. <td class="small-caption category2" valign="top">
  2929. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_NOTE_USER_ID;?>" id="note_user_id_filter"><?php echo lang_get( 'note_user_id_label' )?></a>
  2930. </td>
  2931. <td class="small-caption" valign="top" id="note_user_id_filter_target">
  2932. <?php
  2933. $t_output = '';
  2934. $t_any_found = false;
  2935. if( count( $t_filter[FILTER_PROPERTY_NOTE_USER_ID] ) == 0 ) {
  2936. echo lang_get( 'any' );
  2937. } else {
  2938. $t_first_flag = true;
  2939. foreach( $t_filter[FILTER_PROPERTY_NOTE_USER_ID] as $t_current ) {
  2940. echo '<input type="hidden" name="', FILTER_PROPERTY_NOTE_USER_ID, '[]" value="', $t_current, '" />';
  2941. $t_this_name = '';
  2942. if( filter_field_is_none( $t_current ) ) {
  2943. $t_this_name = lang_get( 'none' );
  2944. } else if( filter_field_is_any( $t_current ) ) {
  2945. $t_any_found = true;
  2946. } else if( filter_field_is_myself( $t_current ) ) {
  2947. if( access_has_project_level( config_get( 'handle_bug_threshold' ) ) ) {
  2948. $t_this_name = '[' . lang_get( 'myself' ) . ']';
  2949. } else {
  2950. $t_any_found = true;
  2951. }
  2952. } else {
  2953. $t_this_name = user_get_name( $t_current );
  2954. }
  2955. if( $t_first_flag != true ) {
  2956. $t_output = $t_output . '<br />';
  2957. } else {
  2958. $t_first_flag = false;
  2959. }
  2960. $t_output = $t_output . $t_this_name;
  2961. }
  2962. if( true == $t_any_found ) {
  2963. echo lang_get( 'any' );
  2964. } else {
  2965. echo string_display( $t_output );
  2966. }
  2967. }
  2968. ?>
  2969. </td>
  2970. <td class="small-caption" valign="top">
  2971. <a href="<?php echo $t_filters_url . 'show_sort';?>" id="show_sort_filter"><?php echo lang_get( 'sort_label' )?></a>
  2972. </td>
  2973. <td class="small-caption" valign="top" id="show_sort_filter_target">
  2974. <?php
  2975. $t_sort_fields = explode( ',', $t_filter[FILTER_PROPERTY_SORT_FIELD_NAME] );
  2976. $t_dir_fields = explode( ',', $t_filter[FILTER_PROPERTY_SORT_DIRECTION] );
  2977. for( $i = 0;$i < 2;$i++ ) {
  2978. if( isset( $t_sort_fields[$i] ) ) {
  2979. if( 0 < $i ) {
  2980. echo ', ';
  2981. }
  2982. $t_sort = $t_sort_fields[$i];
  2983. if( strpos( $t_sort, 'custom_' ) === 0 ) {
  2984. $t_field_name = string_display( lang_get_defaulted( utf8_substr( $t_sort, utf8_strlen( 'custom_' ) ) ) );
  2985. } else {
  2986. $t_field_name = string_get_field_name( $t_sort );
  2987. }
  2988. echo $t_field_name . ' ' . lang_get( 'bugnote_order_' . utf8_strtolower( $t_dir_fields[$i] ) );
  2989. echo '<input type="hidden" name="', FILTER_PROPERTY_SORT_FIELD_NAME, '_', $i, '" value="', $t_sort_fields[$i], '" />';
  2990. echo '<input type="hidden" name="', FILTER_PROPERTY_SORT_DIRECTION, '_', $i, '" value="', $t_dir_fields[$i], '" />';
  2991. }
  2992. }
  2993. ?>
  2994. </td>
  2995. <?php
  2996. if( 'advanced' == $t_view_type ) {
  2997. ?>
  2998. <td class="small-caption" valign="top" colspan="2">
  2999. <a href="<?php echo $t_filters_url . FILTER_PROPERTY_PROJECT_ID;?>" id="project_id_filter"><?php echo lang_get( 'email_project_label' )?></a>
  3000. </td>
  3001. <td class="small-caption" valign="top" id="project_id_filter_target">
  3002. <?php
  3003. $t_output = '';
  3004. if( !is_array( $t_filter[FILTER_PROPERTY_PROJECT_ID] ) ) {
  3005. $t_filter[FILTER_PROPERTY_PROJECT_ID] = Array(
  3006. $t_filter[FILTER_PROPERTY_PROJECT_ID],
  3007. );
  3008. }
  3009. if( count( $t_filter[FILTER_PROPERTY_PROJECT_ID] ) == 0 ) {
  3010. echo lang_get( 'current' );
  3011. } else {
  3012. $t_first_flag = true;
  3013. foreach( $t_filter[FILTER_PROPERTY_PROJECT_ID] as $t_current ) {
  3014. echo '<input type="hidden" name="', FILTER_PROPERTY_PROJECT_ID, '[]" value="', $t_current, '" />';
  3015. $t_this_name = '';
  3016. if( META_FILTER_CURRENT == $t_current ) {
  3017. $t_this_name = lang_get( 'current' );
  3018. } else {
  3019. $t_this_name = project_get_name( $t_current, false );
  3020. }
  3021. if( $t_first_flag != true ) {
  3022. $t_output = $t_output . '<br />';
  3023. } else {
  3024. $t_first_flag = false;
  3025. }
  3026. $t_output = $t_output . string_display_line( $t_this_name );
  3027. }
  3028. echo $t_output;
  3029. }
  3030. ?>
  3031. </td>
  3032. <?php
  3033. if( $t_filter_cols > 6 ) {
  3034. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 5 ) . '">&nbsp;</td>';
  3035. }
  3036. } else {
  3037. if( $t_filter_cols > 3 ) {
  3038. echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 2 ) . '">&nbsp;</td>';
  3039. }
  3040. }
  3041. ?>
  3042. </tr>
  3043. <?php
  3044. }
  3045. // expanded
  3046. ?>
  3047. <tr>
  3048. <td colspan="2">
  3049. <?php
  3050. collapse_icon( 'filter' );
  3051. echo lang_get( 'search' ) . '&nbsp;';
  3052. echo '<input type="text" size="16" name="', FILTER_PROPERTY_SEARCH, '" value="', string_html_specialchars( $t_filter[FILTER_PROPERTY_SEARCH] ), '" />';
  3053. ?>
  3054. <input type="submit" name="filter" class="button-small" value="<?php echo lang_get( 'filter_button' )?>" />
  3055. </td>
  3056. </form>
  3057. <td class="center" colspan="<?php echo( $t_filter_cols - 6 )?>"> <!-- use this label for padding -->
  3058. <?php
  3059. if( ON == config_get( 'dhtml_filters' ) ) {
  3060. $f_switch_view_link = 'view_all_set.php?type=6&view_type=';
  3061. } else {
  3062. $f_switch_view_link = 'view_filters_page.php?view_type=';
  3063. }
  3064. $t_view_filters = config_get( 'view_filters' );
  3065. if(( SIMPLE_ONLY != $t_view_filters ) && ( ADVANCED_ONLY != $t_view_filters ) ) {
  3066. if( 'advanced' == $t_view_type ) {
  3067. print_bracket_link( $f_switch_view_link . 'simple', lang_get( 'simple_filters' ) );
  3068. } else {
  3069. print_bracket_link( $f_switch_view_link . 'advanced', lang_get( 'advanced_filters' ) );
  3070. }
  3071. }
  3072. if( access_has_project_level( config_get( 'create_permalink_threshold' ) ) ) {
  3073. print_bracket_link( 'permalink_page.php?url=' . urlencode( filter_get_url( $t_filter ) ), lang_get( 'create_filter_link' ),
  3074. /* new window = */
  3075. true );
  3076. }
  3077. ?>
  3078. </td>
  3079. <td class="right" colspan="4">
  3080. <?php
  3081. $t_stored_queries_arr = array();
  3082. $t_stored_queries_arr = filter_db_get_available_queries();
  3083. if( count( $t_stored_queries_arr ) > 0 ) {
  3084. ?>
  3085. <form method="get" name="list_queries<?php echo $t_form_name_suffix;?>" action="view_all_set.php">
  3086. <?php # CSRF protection not required here - form does not result in modifications ?>
  3087. <input type="hidden" name="type" value="3" />
  3088. <?php
  3089. if( ON == config_get( 'use_javascript' ) ) {
  3090. echo "<select name=\"source_query_id\" onchange=\"document.forms.list_queries$t_form_name_suffix.submit();\">";
  3091. } else {
  3092. echo '<select name="source_query_id">';
  3093. }
  3094. ?>
  3095. <option value="-1"><?php echo '[' . lang_get( 'reset_query' ) . ']'?></option>
  3096. <option value="-1"></option>
  3097. <?php
  3098. $t_source_query_id = isset( $t_filter['_source_query_id'] ) ? $t_filter['_source_query_id'] : -1;
  3099. foreach( $t_stored_queries_arr as $t_query_id => $t_query_name ) {
  3100. echo '<option value="' . $t_query_id . '" ';
  3101. check_selected( $t_query_id, $t_source_query_id );
  3102. echo '>' . string_display_line( $t_query_name ) . '</option>';
  3103. }
  3104. ?>
  3105. </select>
  3106. <input type="submit" name="switch_to_query_button" class="button-small" value="<?php echo lang_get( 'use_query' )?>" />
  3107. </form>
  3108. <form method="post" name="open_queries" action="query_view_page.php">
  3109. <?php # CSRF protection not required here - form does not result in modifications ?>
  3110. <input type="submit" name="switch_to_query_button" class="button-small" value="<?php echo lang_get( 'open_queries' )?>" />
  3111. </form>
  3112. <?php
  3113. } else {
  3114. ?>
  3115. <form method="get" name="reset_query" action="view_all_set.php">
  3116. <?php # CSRF protection not required here - form does not result in modifications ?>
  3117. <input type="hidden" name="type" value="3" />
  3118. <input type="hidden" name="source_query_id" value="-1" />
  3119. <input type="submit" name="reset_query_button" class="button-small" value="<?php echo lang_get( 'reset_query' )?>" />
  3120. </form>
  3121. <?php
  3122. }
  3123. if( access_has_project_level( config_get( 'stored_query_create_threshold' ) ) ) {
  3124. ?>
  3125. <form method="post" name="save_query" action="query_store_page.php">
  3126. <?php # CSRF protection not required here - form does not result in modifications ?>
  3127. <input type="submit" name="save_query_button" class="button-small" value="<?php echo lang_get( 'save_query' )?>" />
  3128. </form>
  3129. <?php
  3130. }
  3131. ?>
  3132. </td>
  3133. </tr>
  3134. </table>
  3135. <?php
  3136. }
  3137. /**
  3138. * @internal The following functions each print out filter field inputs.
  3139. * They are derived from view_filters_page.php
  3140. * The functions follow a strict naming convention:
  3141. *
  3142. * print_filter_[filter_name]
  3143. *
  3144. * Where [filter_name] is the same as the "name" of the form element for
  3145. * that filter. This naming convention is depended upon by the controller
  3146. * at the end of the script.
  3147. *
  3148. * @todo print functions should be abstracted. Many of these functions
  3149. * are virtually identical except for the property name.
  3150. * Perhaps this code could be made simpler by refactoring into a
  3151. * class so as to avoid all those calls to global(which are pretty ugly)
  3152. * These functions could also be shared by view_filters_page.php
  3153. */
  3154. /**
  3155. * Print the reporter field
  3156. */
  3157. function print_filter_reporter_id() {
  3158. global $t_select_modifier, $t_filter;
  3159. ?>
  3160. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_REPORTER_ID;?>[]">
  3161. <?php
  3162. # if current user is a reporter, and limited reports set to ON, only display that name
  3163. # @@@ thraxisp - access_has_project_level checks greater than or equal to,
  3164. # this assumed that there aren't any holes above REPORTER where the limit would apply
  3165. #
  3166. if(( ON === config_get( 'limit_reporters' ) ) && ( !access_has_project_level( REPORTER + 1 ) ) ) {
  3167. $t_id = auth_get_current_user_id();
  3168. $t_username = user_get_field( $t_id, 'username' );
  3169. $t_realname = user_get_field( $t_id, 'realname' );
  3170. $t_display_name = string_attribute( $t_username );
  3171. if(( isset( $t_realname ) ) && ( $t_realname > '' ) && ( ON == config_get( 'show_realname' ) ) ) {
  3172. $t_display_name = string_attribute( $t_realname );
  3173. }
  3174. echo '<option value="' . $t_id . '" selected="selected">' . $t_display_name . '</option>';
  3175. } else {
  3176. ?>
  3177. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_REPORTER_ID], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3178. <?php
  3179. if( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) {
  3180. echo '<option value="' . META_FILTER_MYSELF . '" ';
  3181. check_selected( $t_filter[FILTER_PROPERTY_REPORTER_ID], META_FILTER_MYSELF );
  3182. echo '>[' . lang_get( 'myself' ) . ']</option>';
  3183. }
  3184. print_reporter_option_list( $t_filter[FILTER_PROPERTY_REPORTER_ID] );
  3185. }?>
  3186. </select>
  3187. <?php
  3188. }
  3189. /**
  3190. * Print the user monitor field
  3191. */
  3192. function print_filter_user_monitor() {
  3193. global $t_select_modifier, $t_filter;
  3194. ?>
  3195. <!-- Monitored by -->
  3196. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_MONITOR_USER_ID;?>[]">
  3197. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3198. <?php
  3199. if( access_has_project_level( config_get( 'monitor_bug_threshold' ) ) ) {
  3200. echo '<option value="' . META_FILTER_MYSELF . '" ';
  3201. check_selected( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID], META_FILTER_MYSELF );
  3202. echo '>[' . lang_get( 'myself' ) . ']</option>';
  3203. }
  3204. $t_threshold = config_get( 'show_monitor_list_threshold' );
  3205. $t_has_project_level = access_has_project_level( $t_threshold );
  3206. if( $t_has_project_level ) {
  3207. print_reporter_option_list( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID] );
  3208. }
  3209. ?>
  3210. </select>
  3211. <?php
  3212. }
  3213. /**
  3214. * print the handler field
  3215. */
  3216. function print_filter_handler_id() {
  3217. global $t_select_modifier, $t_filter, $f_view_type;
  3218. ?>
  3219. <!-- Handler -->
  3220. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_HANDLER_ID;?>[]">
  3221. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_HANDLER_ID], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3222. <?php if( access_has_project_level( config_get( 'view_handler_threshold' ) ) ) {?>
  3223. <option value="<?php echo META_FILTER_NONE?>" <?php check_selected( $t_filter[FILTER_PROPERTY_HANDLER_ID], META_FILTER_NONE );?>>[<?php echo lang_get( 'none' )?>]</option>
  3224. <?php
  3225. if( access_has_project_level( config_get( 'handle_bug_threshold' ) ) ) {
  3226. echo '<option value="' . META_FILTER_MYSELF . '" ';
  3227. check_selected( $t_filter[FILTER_PROPERTY_HANDLER_ID], META_FILTER_MYSELF );
  3228. echo '>[' . lang_get( 'myself' ) . ']</option>';
  3229. }
  3230. print_assign_to_option_list( $t_filter[FILTER_PROPERTY_HANDLER_ID] );
  3231. }?>
  3232. </select>
  3233. <?php
  3234. }
  3235. /**
  3236. * print the category field
  3237. */
  3238. function print_filter_show_category() {
  3239. global $t_select_modifier, $t_filter;
  3240. ?>
  3241. <!-- Category -->
  3242. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_CATEGORY_ID;?>[]">
  3243. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_CATEGORY_ID], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3244. <?php print_category_filter_option_list( $t_filter[FILTER_PROPERTY_CATEGORY_ID] )?>
  3245. </select>
  3246. <?php
  3247. }
  3248. /**
  3249. * print the platform field
  3250. */
  3251. function print_filter_platform() {
  3252. global $t_select_modifier, $t_filter;
  3253. ?>
  3254. <!-- Platform -->
  3255. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_PLATFORM;?>[]">
  3256. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_PLATFORM], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3257. <?php
  3258. log_event( LOG_FILTERING, 'Platform = ' . var_export( $t_filter[FILTER_PROPERTY_PLATFORM], true ) );
  3259. print_platform_option_list( $t_filter[FILTER_PROPERTY_PLATFORM] );
  3260. ?>
  3261. </select>
  3262. <?php
  3263. }
  3264. /**
  3265. * print the os field
  3266. */
  3267. function print_filter_os() {
  3268. global $t_select_modifier, $t_filter;
  3269. ?>
  3270. <!-- OS -->
  3271. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_OS;?>[]">
  3272. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_OS], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3273. <?php print_os_option_list( $t_filter[FILTER_PROPERTY_OS] )?>
  3274. </select>
  3275. <?php
  3276. }
  3277. /**
  3278. * print the os build field
  3279. */
  3280. function print_filter_os_build() {
  3281. global $t_select_modifier, $t_filter;
  3282. ?>
  3283. <!-- OS Build -->
  3284. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_OS_BUILD;?>[]">
  3285. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_OS_BUILD], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3286. <?php print_os_build_option_list( $t_filter[FILTER_PROPERTY_OS_BUILD] )?>
  3287. </select>
  3288. <?php
  3289. }
  3290. /**
  3291. * print the severity field
  3292. */
  3293. function print_filter_show_severity() {
  3294. global $t_select_modifier, $t_filter;
  3295. ?><!-- Severity -->
  3296. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_SEVERITY;?>[]">
  3297. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_SEVERITY], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3298. <?php print_enum_string_option_list( 'severity', $t_filter[FILTER_PROPERTY_SEVERITY] )?>
  3299. </select>
  3300. <?php
  3301. }
  3302. /**
  3303. * print resolution field
  3304. */
  3305. function print_filter_show_resolution() {
  3306. global $t_select_modifier, $t_filter;
  3307. ?><!-- Resolution -->
  3308. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_RESOLUTION;?>[]">
  3309. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_RESOLUTION], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3310. <?php print_enum_string_option_list( 'resolution', $t_filter[FILTER_PROPERTY_RESOLUTION] )?>
  3311. </select>
  3312. <?php
  3313. }
  3314. /**
  3315. * print status field
  3316. */
  3317. function print_filter_show_status() {
  3318. global $t_select_modifier, $t_filter;
  3319. ?> <!-- Status -->
  3320. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_STATUS;?>[]">
  3321. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_STATUS], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3322. <?php print_enum_string_option_list( 'status', $t_filter[FILTER_PROPERTY_STATUS] )?>
  3323. </select>
  3324. <?php
  3325. }
  3326. /**
  3327. * print hide status field
  3328. */
  3329. function print_filter_hide_status() {
  3330. global $t_select_modifier, $t_filter;
  3331. ?><!-- Hide Status -->
  3332. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_HIDE_STATUS;?>[]">
  3333. <option value="<?php echo META_FILTER_NONE?>">[<?php echo lang_get( 'none' )?>]</option>
  3334. <?php print_enum_string_option_list( 'status', $t_filter[FILTER_PROPERTY_HIDE_STATUS] )?>
  3335. </select>
  3336. <?php
  3337. }
  3338. /**
  3339. * print build field
  3340. */
  3341. function print_filter_show_build() {
  3342. global $t_select_modifier, $t_filter;
  3343. ?><!-- Build -->
  3344. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_BUILD;?>[]">
  3345. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_BUILD], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3346. <option value="<?php echo META_FILTER_NONE?>" <?php check_selected( $t_filter[FILTER_PROPERTY_BUILD], META_FILTER_NONE );?>>[<?php echo lang_get( 'none' )?>]</option>
  3347. <?php print_build_option_list( $t_filter[FILTER_PROPERTY_BUILD] )?>
  3348. </select>
  3349. <?php
  3350. }
  3351. /**
  3352. * print version field
  3353. */
  3354. function print_filter_show_version() {
  3355. global $t_select_modifier, $t_filter;
  3356. ?><!-- Version -->
  3357. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_VERSION;?>[]">
  3358. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_VERSION], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3359. <option value="<?php echo META_FILTER_NONE?>" <?php check_selected( $t_filter[FILTER_PROPERTY_VERSION], META_FILTER_NONE );?>>[<?php echo lang_get( 'none' )?>]</option>
  3360. <?php print_version_option_list( $t_filter[FILTER_PROPERTY_VERSION], /* projectId */ null, /* released */ VERSION_ALL, /* leadingBlank */ false, /* withSubs */ true )?>
  3361. </select>
  3362. <?php
  3363. }
  3364. /**
  3365. * print fixed in version field
  3366. */
  3367. function print_filter_show_fixed_in_version() {
  3368. global $t_select_modifier, $t_filter;
  3369. ?><!-- Fixed in Version -->
  3370. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_FIXED_IN_VERSION;?>[]">
  3371. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3372. <option value="<?php echo META_FILTER_NONE?>" <?php check_selected( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION], META_FILTER_NONE );?>>[<?php echo lang_get( 'none' )?>]</option>
  3373. <?php print_version_option_list( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION], /* projectId */ null, /* released */ VERSION_ALL, /* leadingBlank */ false, /* withSubs */ true )?>
  3374. </select>
  3375. <?php
  3376. }
  3377. /**
  3378. * print target version field
  3379. */
  3380. function print_filter_show_target_version() {
  3381. global $t_select_modifier, $t_filter;
  3382. ?><!-- Fixed in Version -->
  3383. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_TARGET_VERSION;?>[]">
  3384. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_TARGET_VERSION], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3385. <option value="<?php echo META_FILTER_NONE?>" <?php check_selected( $t_filter[FILTER_PROPERTY_TARGET_VERSION], META_FILTER_NONE );?>>[<?php echo lang_get( 'none' )?>]</option>
  3386. <?php print_version_option_list( $t_filter[FILTER_PROPERTY_TARGET_VERSION], /* projectId */ null, /* released */ VERSION_ALL, /* leadingBlank */ false, /* withSubs */ true )?>
  3387. </select>
  3388. <?php
  3389. }
  3390. /**
  3391. * print priority field
  3392. */
  3393. function print_filter_show_priority() {
  3394. global $t_select_modifier, $t_filter;
  3395. ?><!-- Priority -->
  3396. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_PRIORITY;?>[]">
  3397. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_PRIORITY], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3398. <?php print_enum_string_option_list( 'priority', $t_filter[FILTER_PROPERTY_PRIORITY] )?>
  3399. </select>
  3400. <?php
  3401. }
  3402. /**
  3403. * print profile field
  3404. */
  3405. function print_filter_show_profile() {
  3406. global $t_select_modifier, $t_filter;
  3407. ?><!-- Profile -->
  3408. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_PROFILE_ID;?>[]">
  3409. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_PROFILE_ID], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3410. <?php print_profile_option_list_for_project( helper_get_current_project(), $t_filter[FILTER_PROPERTY_PROFILE_ID] );?>
  3411. </select>
  3412. <?php
  3413. }
  3414. /**
  3415. * print issues per page field
  3416. */
  3417. function print_filter_per_page() {
  3418. global $t_filter;
  3419. ?><!-- Number of bugs per page -->
  3420. <input type="text" name="<?php echo FILTER_PROPERTY_ISSUES_PER_PAGE;?>" size="3" maxlength="7" value="<?php echo $t_filter[FILTER_PROPERTY_ISSUES_PER_PAGE]?>" />
  3421. <?php
  3422. }
  3423. /**
  3424. * print view state field
  3425. */
  3426. function print_filter_view_state() {
  3427. global $t_select_modifier, $t_filter;
  3428. ?><!-- View Status -->
  3429. <select name="<?php echo FILTER_PROPERTY_VIEW_STATE;?>">
  3430. <?php
  3431. echo '<option value="' . META_FILTER_ANY . '" ';
  3432. check_selected( $t_filter[FILTER_PROPERTY_VIEW_STATE], META_FILTER_ANY );
  3433. echo '>[' . lang_get( 'any' ) . ']</option>';
  3434. echo '<option value="' . VS_PUBLIC . '" ';
  3435. check_selected( $t_filter[FILTER_PROPERTY_VIEW_STATE], VS_PUBLIC );
  3436. echo '>' . lang_get( 'public' ) . '</option>';
  3437. echo '<option value="' . VS_PRIVATE . '" ';
  3438. check_selected( $t_filter[FILTER_PROPERTY_VIEW_STATE], VS_PRIVATE );
  3439. echo '>' . lang_get( 'private' ) . '</option>';
  3440. ?>
  3441. </select>
  3442. <?php
  3443. }
  3444. /**
  3445. * print sticky issues field
  3446. */
  3447. function print_filter_sticky_issues() {
  3448. global $t_filter;
  3449. ?><!-- Show or hide sticky bugs -->
  3450. <input type="checkbox" name="<?php echo FILTER_PROPERTY_STICKY;?>" <?php check_checked( gpc_string_to_bool( $t_filter[FILTER_PROPERTY_STICKY] ), true );?> />
  3451. <?php
  3452. }
  3453. /**
  3454. * print highlight changed field
  3455. */
  3456. function print_filter_highlight_changed() {
  3457. global $t_filter;
  3458. ?><!-- Highlight changed bugs -->
  3459. <input type="text" name="<?php echo FILTER_PROPERTY_HIGHLIGHT_CHANGED;?>" size="3" maxlength="7" value="<?php echo $t_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED]?>" />
  3460. <?php
  3461. }
  3462. /**
  3463. * print filter by date fields with javascript
  3464. * @todo Javascript should be removed and added dynamically
  3465. * via external script
  3466. */
  3467. function print_filter_do_filter_by_date( $p_hide_checkbox = false ) {
  3468. global $t_filter;
  3469. ?>
  3470. <table cellspacing="0" cellpadding="0">
  3471. <?php if( !$p_hide_checkbox ) {
  3472. ?>
  3473. <tr><td colspan="2">
  3474. <input type="checkbox" name="<?php echo FILTER_PROPERTY_FILTER_BY_DATE;?>" <?php
  3475. check_checked( $t_filter[FILTER_PROPERTY_FILTER_BY_DATE], 'on' );
  3476. if( ON == config_get( 'use_javascript' ) ) {
  3477. print "onclick=\"SwitchDateFields();\"";
  3478. }?> />
  3479. <?php echo lang_get( 'use_date_filters' )?>
  3480. </td></tr>
  3481. <?php
  3482. }
  3483. $t_menu_disabled = ( 'on' == $t_filter[FILTER_PROPERTY_FILTER_BY_DATE] ) ? '' : ' disabled ';
  3484. ?>
  3485. <!-- Start date -->
  3486. <tr>
  3487. <td>
  3488. <?php echo lang_get( 'start_date_label' )?>
  3489. </td>
  3490. <td nowrap="nowrap">
  3491. <?php
  3492. $t_chars = preg_split( '//', config_get( 'short_date_format' ), -1, PREG_SPLIT_NO_EMPTY );
  3493. foreach( $t_chars as $t_char ) {
  3494. if( strcasecmp( $t_char, "M" ) == 0 ) {
  3495. echo '<select name="', FILTER_PROPERTY_START_MONTH, '"', $t_menu_disabled, '>';
  3496. print_month_option_list( $t_filter[FILTER_PROPERTY_START_MONTH] );
  3497. print "</select>\n";
  3498. }
  3499. if( strcasecmp( $t_char, "D" ) == 0 ) {
  3500. echo '<select name="', FILTER_PROPERTY_START_DAY, '"', $t_menu_disabled, '>';
  3501. print_day_option_list( $t_filter[FILTER_PROPERTY_START_DAY] );
  3502. print "</select>\n";
  3503. }
  3504. if( strcasecmp( $t_char, "Y" ) == 0 ) {
  3505. echo '<select name="', FILTER_PROPERTY_START_YEAR, '"', $t_menu_disabled, '>';
  3506. print_year_option_list( $t_filter[FILTER_PROPERTY_START_YEAR] );
  3507. print "</select>\n";
  3508. }
  3509. }
  3510. ?>
  3511. </td>
  3512. </tr>
  3513. <!-- End date -->
  3514. <tr>
  3515. <td>
  3516. <?php echo lang_get( 'end_date_label' )?>
  3517. </td>
  3518. <td>
  3519. <?php
  3520. $t_chars = preg_split( '//', config_get( 'short_date_format' ), -1, PREG_SPLIT_NO_EMPTY );
  3521. foreach( $t_chars as $t_char ) {
  3522. if( strcasecmp( $t_char, "M" ) == 0 ) {
  3523. echo '<select name="', FILTER_PROPERTY_END_MONTH, '"', $t_menu_disabled, '>';
  3524. print_month_option_list( $t_filter[FILTER_PROPERTY_END_MONTH] );
  3525. print "</select>\n";
  3526. }
  3527. if( strcasecmp( $t_char, "D" ) == 0 ) {
  3528. echo '<select name="', FILTER_PROPERTY_END_DAY, '"', $t_menu_disabled, '>';
  3529. print_day_option_list( $t_filter[FILTER_PROPERTY_END_DAY] );
  3530. print "</select>\n";
  3531. }
  3532. if( strcasecmp( $t_char, "Y" ) == 0 ) {
  3533. echo '<select name="', FILTER_PROPERTY_END_YEAR, '"', $t_menu_disabled, '>';
  3534. print_year_option_list( $t_filter[FILTER_PROPERTY_END_YEAR] );
  3535. print "</select>\n";
  3536. }
  3537. }
  3538. ?>
  3539. </td>
  3540. </tr>
  3541. </table>
  3542. <?php
  3543. }
  3544. /**
  3545. * print relationship fields
  3546. */
  3547. function print_filter_relationship_type() {
  3548. global $t_filter;
  3549. $c_reltype_value = $t_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE];
  3550. if( !$c_reltype_value ) {
  3551. $c_reltype_value = -1;
  3552. }
  3553. relationship_list_box( $c_reltype_value, "relationship_type", true );
  3554. echo '<input type="text" name="', FILTER_PROPERTY_RELATIONSHIP_BUG, '" size="5" maxlength="10" value="', $t_filter[FILTER_PROPERTY_RELATIONSHIP_BUG], '" />';
  3555. }
  3556. /**
  3557. * print tag fields
  3558. */
  3559. function print_filter_tag_string() {
  3560. if ( !access_has_global_level( config_get( 'tag_view_threshold' ) ) ) {
  3561. return;
  3562. }
  3563. global $t_filter;
  3564. $t_tag_string = $t_filter[FILTER_PROPERTY_TAG_STRING];
  3565. if( $t_filter[FILTER_PROPERTY_TAG_SELECT] != 0 && tag_exists( $t_filter[FILTER_PROPERTY_TAG_SELECT] ) ) {
  3566. $t_tag_string .= ( is_blank( $t_tag_string ) ? '' : config_get( 'tag_separator' ) );
  3567. $t_tag_string .= tag_get_field( $t_filter[FILTER_PROPERTY_TAG_SELECT], 'name' );
  3568. }
  3569. ?>
  3570. <input type="hidden" id="tag_separator" value="<?php echo config_get( 'tag_separator' )?>" />
  3571. <input type="text" name="<?php echo FILTER_PROPERTY_TAG_STRING;?>" id="<?php echo FILTER_PROPERTY_TAG_STRING;?>" size="40" value="<?php echo string_attribute( $t_tag_string )?>" />
  3572. <select <?php echo helper_get_tab_index()?> name="<?php echo FILTER_PROPERTY_TAG_SELECT;?>" id="<?php echo FILTER_PROPERTY_TAG_SELECT;?>">
  3573. <?php print_tag_option_list();?>
  3574. </select>
  3575. <?php
  3576. }
  3577. /**
  3578. * print note reporter field
  3579. */
  3580. function print_filter_note_user_id() {
  3581. global $t_select_modifier, $t_filter, $f_view_type;
  3582. ?>
  3583. <!-- BUGNOTE REPORTER -->
  3584. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_NOTE_USER_ID;?>[]">
  3585. <option value="<?php echo META_FILTER_ANY?>" <?php check_selected( $t_filter[FILTER_PROPERTY_NOTE_USER_ID], META_FILTER_ANY );?>>[<?php echo lang_get( 'any' )?>]</option>
  3586. <?php if( access_has_project_level( config_get( 'view_handler_threshold' ) ) ) {?>
  3587. <option value="<?php echo META_FILTER_NONE?>" <?php check_selected( $t_filter[FILTER_PROPERTY_NOTE_USER_ID], META_FILTER_NONE );?>>[<?php echo lang_get( 'none' )?>]</option>
  3588. <?php
  3589. if( access_has_project_level( config_get( 'handle_bug_threshold' ) ) ) {
  3590. echo '<option value="' . META_FILTER_MYSELF . '" ';
  3591. check_selected( $t_filter[FILTER_PROPERTY_NOTE_USER_ID], META_FILTER_MYSELF );
  3592. echo '>[' . lang_get( 'myself' ) . ']</option>';
  3593. }
  3594. print_assign_to_option_list( $t_filter[FILTER_PROPERTY_NOTE_USER_ID] );
  3595. }
  3596. ?>
  3597. </select>
  3598. <?php
  3599. }
  3600. /**
  3601. * Print plugin filter fields as defined by MantisFilter objects.
  3602. * @param string Field name
  3603. * @param object Filter object
  3604. */
  3605. function print_filter_plugin_field( $p_field_name, $p_filter_object ) {
  3606. global $t_select_modifier, $t_filter, $f_view_type;
  3607. $t_size = (int)$p_filter_object->size;
  3608. switch( $p_filter_object->type ) {
  3609. case FILTER_TYPE_STRING:
  3610. echo '<input name="', string_attribute( $p_field_name ), '"',
  3611. ( $t_size > 0 ? " size=\"$t_size\"" : '' ), ' value="',
  3612. string_attribute( $t_filter[ $p_field_name ] ), '"/>';
  3613. break;
  3614. case FILTER_TYPE_INT:
  3615. echo '<input name="', string_attribute( $p_field_name ), '"',
  3616. ( $t_size > 0 ? " size=\"$t_size\"" : '' ), ' value="',
  3617. (int) $t_filter[ $p_field_name ], '"/>';
  3618. break;
  3619. case FILTER_TYPE_BOOLEAN:
  3620. echo '<input name="', string_attribute( $p_field_name ), '" type="checkbox"',
  3621. ( $t_size > 0 ? " size=\"$t_size\"" : '' ), check_checked( (bool) $t_filter[ $p_field_name ] ) , '"/>';
  3622. break;
  3623. case FILTER_TYPE_MULTI_STRING:
  3624. echo '<select ', $t_select_modifier, ( $t_size > 0 ? " size=\"$t_size\"" : '' ), ' name="',
  3625. string_attribute( $p_field_name ), '[]">', '<option value="', META_FILTER_ANY, '" ',
  3626. check_selected( $t_filter[ $p_field_name ], META_FILTER_ANY ), '>[', lang_get( 'any' ), ']</option>';
  3627. foreach( $p_filter_object->options() as $t_option_value => $t_option_name ) {
  3628. echo '<option value="', string_attribute( $t_option_value ), '" ',
  3629. check_selected( $t_filter[ $p_field_name ], $t_option_value ), '>',
  3630. string_display_line( $t_option_name ), '</option>';
  3631. }
  3632. echo '</select>';
  3633. break;
  3634. case FILTER_TYPE_MULTI_INT:
  3635. echo '<select ', $t_select_modifier, ( $t_size > 0 ? " size=\"$t_size\"" : '' ), ' name="',
  3636. string_attribute( $p_field_name ), '[]">', '<option value="', META_FILTER_ANY, '" ',
  3637. check_selected( $t_filter[ $p_field_name ], META_FILTER_ANY ), '>[', lang_get( 'any' ), ']</option>';
  3638. foreach( $p_filter_object->options() as $t_option_value => $t_option_name ) {
  3639. echo '<option value="', (int)$t_option_value, '" ',
  3640. check_selected( $t_filter[ $p_field_name ], (int)$t_option_value ), '>',
  3641. string_display_line( $t_option_name ), '</option>';
  3642. }
  3643. echo '</select>';
  3644. break;
  3645. }
  3646. }
  3647. /**
  3648. * print custom fields
  3649. * @param int $p_field_id
  3650. */
  3651. function print_filter_custom_field( $p_field_id ) {
  3652. global $t_filter, $t_accessible_custom_fields_names, $t_accessible_custom_fields_types, $t_accessible_custom_fields_values, $t_accessible_custom_fields_ids, $t_select_modifier;
  3653. $j = array_search( $p_field_id, $t_accessible_custom_fields_ids );
  3654. if( $j === null || $j === false ) {
  3655. # Note: Prior to PHP 4.2.0, array_search() returns NULL on failure instead of FALSE.
  3656. ?>
  3657. <span style="color:red;weight:bold;">
  3658. unknown custom filter (custom <?php $p_field_id;?>)
  3659. </span>
  3660. <?php
  3661. } else if( isset( $t_accessible_custom_fields_names[$j] ) ) {
  3662. if( $t_accessible_custom_fields_types[$j] == CUSTOM_FIELD_TYPE_DATE ) {
  3663. print_filter_custom_field_date( $j, $p_field_id );
  3664. } else {
  3665. echo '<select ' . $t_select_modifier . ' name="custom_field_' . $p_field_id . '[]">';
  3666. echo '<option value="' . META_FILTER_ANY . '" ';
  3667. check_selected( $t_filter['custom_fields'][$p_field_id], META_FILTER_ANY );
  3668. echo '>[' . lang_get( 'any' ) . ']</option>';
  3669. # don't show META_FILTER_NONE for enumerated types as it's not possible for them to be blank
  3670. if( !in_array( $t_accessible_custom_fields_types[$j], array( CUSTOM_FIELD_TYPE_ENUM, CUSTOM_FIELD_TYPE_LIST, CUSTOM_FIELD_TYPE_MULTILIST ) ) ) {
  3671. echo '<option value="' . META_FILTER_NONE . '" ';
  3672. check_selected( $t_filter['custom_fields'][$p_field_id], META_FILTER_NONE );
  3673. echo '>[' . lang_get( 'none' ) . ']</option>';
  3674. }
  3675. if( is_array( $t_accessible_custom_fields_values[$j] ) ) {
  3676. $t_max_length = config_get( 'max_dropdown_length' );
  3677. foreach( $t_accessible_custom_fields_values[$j] as $t_item ) {
  3678. if(( utf8_strtolower( $t_item ) !== META_FILTER_ANY ) && ( utf8_strtolower( $t_item ) !== META_FILTER_NONE ) ) {
  3679. echo '<option value="' . string_attribute( $t_item ) . '" ';
  3680. if( isset( $t_filter['custom_fields'][$p_field_id] ) ) {
  3681. check_selected( $t_filter['custom_fields'][$p_field_id], $t_item );
  3682. }
  3683. echo '>' . string_attribute( string_shorten( $t_item, $t_max_length ) ) . '</option>' . "\n";
  3684. }
  3685. }
  3686. }
  3687. echo '</select>';
  3688. }
  3689. }
  3690. }
  3691. /**
  3692. * print sort fields
  3693. */
  3694. function print_filter_show_sort() {
  3695. global $t_filter;
  3696. # get all of the displayed fields for sort, then drop ones that
  3697. # are not appropriate and translate the rest
  3698. $t_fields = helper_get_columns_to_view();
  3699. $t_n_fields = count( $t_fields );
  3700. $t_shown_fields[''] = '';
  3701. for( $i = 0;$i < $t_n_fields;$i++ ) {
  3702. if( !in_array( $t_fields[$i], array( 'selection', 'edit', 'bugnotes_count', 'attachment' ) ) ) {
  3703. if( strpos( $t_fields[$i], 'custom_' ) === 0 ) {
  3704. $t_field_name = string_display( lang_get_defaulted( utf8_substr( $t_fields[$i], utf8_strlen( 'custom_' ) ) ) );
  3705. } else {
  3706. $t_field_name = string_get_field_name( $t_fields[$i] );
  3707. }
  3708. $t_shown_fields[$t_fields[$i]] = $t_field_name;
  3709. }
  3710. }
  3711. $t_shown_dirs[''] = '';
  3712. $t_shown_dirs['ASC'] = lang_get( 'bugnote_order_asc' );
  3713. $t_shown_dirs['DESC'] = lang_get( 'bugnote_order_desc' );
  3714. # get default values from filter structure
  3715. $t_sort_fields = explode( ',', $t_filter[FILTER_PROPERTY_SORT_FIELD_NAME] );
  3716. $t_dir_fields = explode( ',', $t_filter[FILTER_PROPERTY_SORT_DIRECTION] );
  3717. if( !isset( $t_sort_fields[1] ) ) {
  3718. $t_sort_fields[1] = '';
  3719. $t_dir_fields[1] = '';
  3720. }
  3721. # if there are fields to display, show the dropdowns
  3722. if( count( $t_fields ) > 0 ) {
  3723. # display a primary and secondary sort fields
  3724. echo '<select name="', FILTER_PROPERTY_SORT_FIELD_NAME, '_0">';
  3725. foreach( $t_shown_fields as $key => $val ) {
  3726. echo '<option value="' . $key . '"';
  3727. check_selected( $key, $t_sort_fields[0] );
  3728. echo '>' . $val . '</option>';
  3729. }
  3730. echo '</select>';
  3731. echo '<select name="', FILTER_PROPERTY_SORT_DIRECTION, '_0">';
  3732. foreach( $t_shown_dirs as $key => $val ) {
  3733. echo '<option value="' . $key . '"';
  3734. check_selected( $key, $t_dir_fields[0] );
  3735. echo '>' . $val . '</option>';
  3736. }
  3737. echo '</select>';
  3738. echo ', ';
  3739. # for secondary sort
  3740. echo '<select name="', FILTER_PROPERTY_SORT_FIELD_NAME, '_1">';
  3741. foreach( $t_shown_fields as $key => $val ) {
  3742. echo '<option value="' . $key . '"';
  3743. check_selected( $key, $t_sort_fields[1] );
  3744. echo '>' . $val . '</option>';
  3745. }
  3746. echo '</select>';
  3747. echo '<select name="', FILTER_PROPERTY_SORT_DIRECTION, '_1">';
  3748. foreach( $t_shown_dirs as $key => $val ) {
  3749. echo '<option value="' . $key . '"';
  3750. check_selected( $key, $t_dir_fields[1] );
  3751. echo '>' . $val . '</option>';
  3752. }
  3753. echo '</select>';
  3754. } else {
  3755. echo lang_get_defaulted( 'last_updated' ) . lang_get( 'bugnote_order_desc' );
  3756. echo '<input type="hidden" name="', FILTER_PROPERTY_SORT_FIELD_NAME, '_1" value="last_updated" />';
  3757. echo '<input type="hidden" name="', FILTER_PROPERTY_SORT_DIRECTION, '_1" value="DESC" />';
  3758. }
  3759. }
  3760. /**
  3761. * print custom field date fields
  3762. * @param int $p_field_num
  3763. * @param int $p_field_id
  3764. */
  3765. function print_filter_custom_field_date( $p_field_num, $p_field_id ) {
  3766. global $t_filter, $t_accessible_custom_fields_names, $t_accessible_custom_fields_types, $t_accessible_custom_fields_values, $t_accessible_custom_fields_ids, $t_select_modifier;
  3767. $t_js_toggle_func = 'toggle_custom_date_field_' . $p_field_id . '_controls';
  3768. # Resort the values so there ordered numerically, they are sorted as strings otherwise which
  3769. # may be wrong for dates before early 2001.
  3770. if( is_array( $t_accessible_custom_fields_values[$p_field_num] ) ) {
  3771. array_multisort( $t_accessible_custom_fields_values[$p_field_num], SORT_NUMERIC, SORT_ASC );
  3772. }
  3773. if( isset( $t_accessible_custom_fields_values[$p_field_num][0] ) ) {
  3774. $t_sel_start_year = date( 'Y', $t_accessible_custom_fields_values[$p_field_num][0] );
  3775. }
  3776. $t_count = count( $t_accessible_custom_fields_values[$p_field_num] );
  3777. if( isset( $t_accessible_custom_fields_values[$p_field_num][$t_count - 1] ) ) {
  3778. $t_sel_end_year = date( 'Y', $t_accessible_custom_fields_values[$p_field_num][$t_count - 1] );
  3779. }
  3780. $t_start = date( 'U' );
  3781. # Default to today in filters..
  3782. $t_end = $t_start;
  3783. if( isset( $t_filter['custom_fields'][$p_field_id][1] ) ) {
  3784. $t_start_time = $t_filter['custom_fields'][$p_field_id][1];
  3785. } else {
  3786. $t_start_time = 0;
  3787. }
  3788. if( isset( $t_filter['custom_fields'][$p_field_id][2] ) ) {
  3789. $t_end_time = $t_filter['custom_fields'][$p_field_id][2];
  3790. } else {
  3791. $t_end_time = 0;
  3792. }
  3793. $t_start_disable = true;
  3794. $t_end_disable = true;
  3795. // if $t_filter['custom_fields'][$p_field_id][0] is not set (ie no filter), we will drop through the
  3796. // following switch and use the default values above, so no need to check if stuff is set or not.
  3797. switch( $t_filter['custom_fields'][$p_field_id][0] ) {
  3798. case CUSTOM_FIELD_DATE_ANY:
  3799. case CUSTOM_FIELD_DATE_NONE:
  3800. break;
  3801. case CUSTOM_FIELD_DATE_BETWEEN:
  3802. $t_start_disable = false;
  3803. $t_end_disable = false;
  3804. $t_start = $t_start_time;
  3805. $t_end = $t_end_time;
  3806. break;
  3807. case CUSTOM_FIELD_DATE_ONORBEFORE:
  3808. $t_start_disable = false;
  3809. $t_start = $t_end_time;
  3810. break;
  3811. case CUSTOM_FIELD_DATE_BEFORE:
  3812. $t_start_disable = false;
  3813. $t_start = $t_end_time;
  3814. break;
  3815. case CUSTOM_FIELD_DATE_ON:
  3816. $t_start_disable = false;
  3817. $t_start = $t_start_time;
  3818. break;
  3819. case CUSTOM_FIELD_DATE_AFTER:
  3820. $t_start_disable = false;
  3821. $t_start = $t_start_time;
  3822. break;
  3823. case CUSTOM_FIELD_DATE_ONORAFTER:
  3824. $t_start_disable = false;
  3825. $t_start = $t_start_time;
  3826. break;
  3827. }
  3828. echo "\n<table cellspacing=\"0\" cellpadding=\"0\"><tr><td>\n";
  3829. echo "<select size=\"1\" name=\"custom_field_" . $p_field_id . "_control\" OnChange=\"" . $t_js_toggle_func . "();\">\n";
  3830. echo '<option value="' . CUSTOM_FIELD_DATE_ANY . '"';
  3831. check_selected( $t_filter['custom_fields'][$p_field_id][0], CUSTOM_FIELD_DATE_ANY );
  3832. echo '>' . lang_get( 'any' ) . '</option>' . "\n";
  3833. echo '<option value="' . CUSTOM_FIELD_DATE_NONE . '"';
  3834. check_selected( $t_filter['custom_fields'][$p_field_id][0], CUSTOM_FIELD_DATE_NONE );
  3835. echo '>' . lang_get( 'none' ) . '</option>' . "\n";
  3836. echo '<option value="' . CUSTOM_FIELD_DATE_BETWEEN . '"';
  3837. check_selected( $t_filter['custom_fields'][$p_field_id][0], CUSTOM_FIELD_DATE_BETWEEN );
  3838. echo '>' . lang_get( 'between_date' ) . '</option>' . "\n";
  3839. echo '<option value="' . CUSTOM_FIELD_DATE_ONORBEFORE . '"';
  3840. check_selected( $t_filter['custom_fields'][$p_field_id][0], CUSTOM_FIELD_DATE_ONORBEFORE );
  3841. echo '>' . lang_get( 'on_or_before_date' ) . '</option>' . "\n";
  3842. echo '<option value="' . CUSTOM_FIELD_DATE_BEFORE . '"';
  3843. check_selected( $t_filter['custom_fields'][$p_field_id][0], CUSTOM_FIELD_DATE_BEFORE );
  3844. echo '>' . lang_get( 'before_date' ) . '</option>' . "\n";
  3845. echo '<option value="' . CUSTOM_FIELD_DATE_ON . '"';
  3846. check_selected( $t_filter['custom_fields'][$p_field_id][0], CUSTOM_FIELD_DATE_ON );
  3847. echo '>' . lang_get( 'on_date' ) . '</option>' . "\n";
  3848. echo '<option value="' . CUSTOM_FIELD_DATE_AFTER . '"';
  3849. check_selected( $t_filter['custom_fields'][$p_field_id][0], CUSTOM_FIELD_DATE_AFTER );
  3850. echo '>' . lang_get( 'after_date' ) . '</option>' . "\n";
  3851. echo '<option value="' . CUSTOM_FIELD_DATE_ONORAFTER . '"';
  3852. check_selected( $t_filter['custom_fields'][$p_field_id][0], CUSTOM_FIELD_DATE_ONORAFTER );
  3853. echo '>' . lang_get( 'on_or_after_date' ) . '</option>' . "\n";
  3854. echo '</select>' . "\n";
  3855. echo "</td></tr>\n<tr><td>";
  3856. print_date_selection_set( 'custom_field_' . $p_field_id . '_start', config_get( 'short_date_format' ), $t_start, $t_start_disable, false, $t_sel_start_year, $t_sel_end_year );
  3857. print "</td></tr>\n<tr><td>";
  3858. print_date_selection_set( 'custom_field_' . $p_field_id . '_end', config_get( 'short_date_format' ), $t_end, $t_end_disable, false, $t_sel_start_year, $t_sel_end_year );
  3859. print "</td></tr>\n</table>";
  3860. }
  3861. /**
  3862. * print project field
  3863. */
  3864. function print_filter_project_id() {
  3865. global $t_select_modifier, $t_filter, $f_view_type;
  3866. ?>
  3867. <!-- Project -->
  3868. <select <?php echo $t_select_modifier;?> name="<?php echo FILTER_PROPERTY_PROJECT_ID;?>[]">
  3869. <option value="<?php echo META_FILTER_CURRENT?>" <?php check_selected( $t_filter[FILTER_PROPERTY_PROJECT_ID], META_FILTER_CURRENT );?>>[<?php echo lang_get( 'current' )?>]</option>
  3870. <?php print_project_option_list( $t_filter[FILTER_PROPERTY_PROJECT_ID] )?>
  3871. </select>
  3872. <?php
  3873. }
  3874. /**
  3875. * Prints a multi-value filter field.
  3876. * @param string $p_field_name
  3877. * @param mixed $p_field_value
  3878. */
  3879. function print_multivalue_field( $p_field_name, $p_field_value ) {
  3880. $t_output = '';
  3881. $t_any_found = false;
  3882. if( count( $p_field_value ) == 0 ) {
  3883. echo lang_get( 'any' );
  3884. } else {
  3885. $t_first_flag = true;
  3886. $t_field_value = is_array( $p_field_value ) ? $p_field_value : array( $p_field_value );
  3887. foreach( $t_field_value as $t_current ) {
  3888. $t_current = stripslashes( $t_current );
  3889. ?>
  3890. <input type="hidden" name="<?php echo $p_field_name?>[]" value="<?php echo string_display( $t_current );?>" />
  3891. <?php
  3892. $t_this_string = '';
  3893. if((( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) ) || ( is_blank( $t_current ) ) ) {
  3894. $t_any_found = true;
  3895. } else {
  3896. $t_this_string = string_display( $t_current );
  3897. }
  3898. if( $t_first_flag != true ) {
  3899. $t_output .= '<br />';
  3900. } else {
  3901. $t_first_flag = false;
  3902. }
  3903. $t_output .= $t_this_string;
  3904. }
  3905. if( true == $t_any_found ) {
  3906. echo lang_get( 'any' );
  3907. } else {
  3908. echo $t_output;
  3909. }
  3910. }
  3911. }
  3912. # ==========================================================================
  3913. # CACHING
  3914. # ==========================================================================
  3915. /**
  3916. * @internal SECURITY NOTE: cache globals are initialized here to prevent them
  3917. * being spoofed if register_globals is turned on.
  3918. * We cache filter requests to reduce the number of SQL queries
  3919. * @global mixed $g_cache_filter
  3920. * @global mixed $g_cache_filter_db_filters
  3921. */
  3922. $g_cache_filter = array();
  3923. $g_cache_filter_db_filters = array();
  3924. /**
  3925. * Cache a filter row if necessary and return the cached copy
  3926. * If the second parameter is true (default), trigger an error
  3927. * if the filter can't be found. If the second parameter is
  3928. * false, return false if the filter can't be found.
  3929. * @param int $p_filter_id
  3930. * @param bool $p_trigger_errors
  3931. * @return mixed
  3932. */
  3933. function filter_cache_row( $p_filter_id, $p_trigger_errors = true ) {
  3934. global $g_cache_filter;
  3935. $c_filter_id = db_prepare_int( $p_filter_id );
  3936. $t_filters_table = db_get_table( 'filters' );
  3937. if( isset( $g_cache_filter[$c_filter_id] ) ) {
  3938. return $g_cache_filter[$c_filter_id];
  3939. }
  3940. $query = 'SELECT *
  3941. FROM ' . $t_filters_table . '
  3942. WHERE id=' . db_param();
  3943. $result = db_query_bound( $query, Array( $c_filter_id ) );
  3944. if( 0 == db_num_rows( $result ) ) {
  3945. if( $p_trigger_errors ) {
  3946. error_parameters( $p_filter_id );
  3947. trigger_error( ERROR_FILTER_NOT_FOUND, ERROR );
  3948. } else {
  3949. return false;
  3950. }
  3951. }
  3952. $row = db_fetch_array( $result );
  3953. $g_cache_filter[$c_filter_id] = $row;
  3954. return $row;
  3955. }
  3956. /**
  3957. * Clear the filter cache (or just the given id if specified)
  3958. * @param int $p_filter_id
  3959. * @return bool
  3960. */
  3961. function filter_clear_cache( $p_filter_id = null ) {
  3962. global $g_cache_filter;
  3963. if( null === $p_filter_id ) {
  3964. $g_cache_filter = array();
  3965. } else {
  3966. $c_filter_id = db_prepare_int( $p_filter_id );
  3967. unset( $g_cache_filter[$c_filter_id] );
  3968. }
  3969. return true;
  3970. }
  3971. # ==========================================================================
  3972. # FILTER DB FUNCTIONS
  3973. # ==========================================================================
  3974. /**
  3975. * Add a filter to the database for the current user
  3976. * @param int $p_project_id
  3977. * @param bool $p_is_public
  3978. * @param string $p_name
  3979. * @param string $p_filter_string
  3980. * @return int
  3981. */
  3982. function filter_db_set_for_current_user( $p_project_id, $p_is_public, $p_name, $p_filter_string ) {
  3983. $t_user_id = auth_get_current_user_id();
  3984. $c_project_id = db_prepare_int( $p_project_id );
  3985. $c_is_public = db_prepare_bool( $p_is_public, false );
  3986. $t_filters_table = db_get_table( 'filters' );
  3987. # check that the user can save non current filters (if required)
  3988. if(( ALL_PROJECTS <= $c_project_id ) && ( !is_blank( $p_name ) ) && ( !access_has_project_level( config_get( 'stored_query_create_threshold' ) ) ) ) {
  3989. return -1;
  3990. }
  3991. # ensure that we're not making this filter public if we're not allowed
  3992. if( !access_has_project_level( config_get( 'stored_query_create_shared_threshold' ) ) ) {
  3993. $c_is_public = db_prepare_bool( false );
  3994. }
  3995. # Do I need to update or insert this value?
  3996. $query = "SELECT id FROM $t_filters_table
  3997. WHERE user_id=" . db_param() . "
  3998. AND project_id=" . db_param() . "
  3999. AND name=" . db_param();
  4000. $result = db_query_bound( $query, Array( $t_user_id, $c_project_id, $p_name ) );
  4001. if( db_num_rows( $result ) > 0 ) {
  4002. $row = db_fetch_array( $result );
  4003. $query = "UPDATE $t_filters_table
  4004. SET is_public=" . db_param() . ",
  4005. filter_string=" . db_param() . "
  4006. WHERE id=" . db_param();
  4007. db_query_bound( $query, Array( $c_is_public, $p_filter_string, $row['id'] ) );
  4008. return $row['id'];
  4009. } else {
  4010. $query = "INSERT INTO $t_filters_table
  4011. ( user_id, project_id, is_public, name, filter_string )
  4012. VALUES
  4013. ( " . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ' )';
  4014. db_query_bound( $query, Array( $t_user_id, $c_project_id, $c_is_public, $p_name, $p_filter_string ) );
  4015. # Recall the query, we want the filter ID
  4016. $query = "SELECT id
  4017. FROM $t_filters_table
  4018. WHERE user_id=" . db_param() . "
  4019. AND project_id=" . db_param() . "
  4020. AND name=" . db_param();
  4021. $result = db_query_bound( $query, Array( $t_user_id, $c_project_id, $p_name ) );
  4022. if( db_num_rows( $result ) > 0 ) {
  4023. $row = db_fetch_array( $result );
  4024. return $row['id'];
  4025. }
  4026. return -1;
  4027. }
  4028. }
  4029. /**
  4030. * This function returns the filter string that is
  4031. * tied to the unique id parameter. If the user doesn't
  4032. * have permission to see this filter, the function
  4033. * returns null
  4034. * @param int $p_filter_id
  4035. * @param int $p_user_id
  4036. * @return mixed
  4037. */
  4038. function filter_db_get_filter( $p_filter_id, $p_user_id = null ) {
  4039. global $g_cache_filter_db_filters;
  4040. $t_filters_table = db_get_table( 'filters' );
  4041. $c_filter_id = db_prepare_int( $p_filter_id );
  4042. if( isset( $g_cache_filter_db_filters[$p_filter_id] ) ) {
  4043. if( $g_cache_filter_db_filters[$p_filter_id] === false ) {
  4044. return null;
  4045. }
  4046. return $g_cache_filter_db_filters[$p_filter_id];
  4047. }
  4048. if( null === $p_user_id ) {
  4049. $t_user_id = auth_get_current_user_id();
  4050. } else {
  4051. $t_user_id = $p_user_id;
  4052. }
  4053. $query = 'SELECT * FROM ' . $t_filters_table . ' WHERE id=' . db_param();
  4054. $result = db_query_bound( $query, Array( $c_filter_id ) );
  4055. if( db_num_rows( $result ) > 0 ) {
  4056. $row = db_fetch_array( $result );
  4057. if( $row['user_id'] != $t_user_id ) {
  4058. if( $row['is_public'] != true ) {
  4059. return null;
  4060. }
  4061. }
  4062. # check that the user has access to non current filters
  4063. if(( ALL_PROJECTS <= $row['project_id'] ) && ( !is_blank( $row['name'] ) ) && ( !access_has_project_level( config_get( 'stored_query_use_threshold', $row['project_id'], $t_user_id ) ) ) ) {
  4064. return null;
  4065. }
  4066. $g_cache_filter_db_filters[$p_filter_id] = $row['filter_string'];
  4067. return $row['filter_string'];
  4068. } else {
  4069. $g_cache_filter_db_filters[$p_filter_id] = false;
  4070. return false;
  4071. }
  4072. }
  4073. /**
  4074. * @param int $p_project_id
  4075. * @param int $p_user_id
  4076. * @return int
  4077. */
  4078. function filter_db_get_project_current( $p_project_id, $p_user_id = null ) {
  4079. $t_filters_table = db_get_table( 'filters' );
  4080. $c_project_id = db_prepare_int( $p_project_id );
  4081. $c_project_id = $c_project_id * -1;
  4082. if( null === $p_user_id ) {
  4083. $c_user_id = auth_get_current_user_id();
  4084. } else {
  4085. $c_user_id = db_prepare_int( $p_user_id );
  4086. }
  4087. # we store current filters for each project with a special project index
  4088. $query = "SELECT *
  4089. FROM $t_filters_table
  4090. WHERE user_id=" . db_param() . "
  4091. AND project_id=" . db_param() . "
  4092. AND name=" . db_param();
  4093. $result = db_query_bound( $query, Array( $c_user_id, $c_project_id, '' ) );
  4094. if( db_num_rows( $result ) > 0 ) {
  4095. $row = db_fetch_array( $result );
  4096. return $row['id'];
  4097. }
  4098. return null;
  4099. }
  4100. /**
  4101. * Query for the filter name using the filter id
  4102. * @param int $p_filter_id
  4103. * @return string
  4104. */
  4105. function filter_db_get_name( $p_filter_id ) {
  4106. $t_filters_table = db_get_table( 'filters' );
  4107. $c_filter_id = db_prepare_int( $p_filter_id );
  4108. $query = 'SELECT * FROM ' . $t_filters_table . ' WHERE id=' . db_param();
  4109. $result = db_query_bound( $query, Array( $c_filter_id ) );
  4110. if( db_num_rows( $result ) > 0 ) {
  4111. $row = db_fetch_array( $result );
  4112. if( $row['user_id'] != auth_get_current_user_id() ) {
  4113. if( $row['is_public'] != true ) {
  4114. return null;
  4115. }
  4116. }
  4117. return $row['name'];
  4118. }
  4119. return null;
  4120. }
  4121. /**
  4122. * Check if the current user has permissions to delete the stored query
  4123. * @param $p_filter_id
  4124. * @return bool
  4125. */
  4126. function filter_db_can_delete_filter( $p_filter_id ) {
  4127. $t_filters_table = db_get_table( 'filters' );
  4128. $c_filter_id = db_prepare_int( $p_filter_id );
  4129. $t_user_id = auth_get_current_user_id();
  4130. # Administrators can delete any filter
  4131. if( user_is_administrator( $t_user_id ) ) {
  4132. return true;
  4133. }
  4134. $query = "SELECT id
  4135. FROM $t_filters_table
  4136. WHERE id=" . db_param() . "
  4137. AND user_id=" . db_param() . "
  4138. AND project_id!=" . db_param();
  4139. $result = db_query_bound( $query, Array( $c_filter_id, $t_user_id, -1 ) );
  4140. if( db_num_rows( $result ) > 0 ) {
  4141. return true;
  4142. }
  4143. return false;
  4144. }
  4145. /**
  4146. * Delete the filter specified by $p_filter_id
  4147. * @param $p_filter_id
  4148. * @return bool
  4149. */
  4150. function filter_db_delete_filter( $p_filter_id ) {
  4151. $t_filters_table = db_get_table( 'filters' );
  4152. $c_filter_id = db_prepare_int( $p_filter_id );
  4153. $t_user_id = auth_get_current_user_id();
  4154. if( !filter_db_can_delete_filter( $c_filter_id ) ) {
  4155. return false;
  4156. }
  4157. $query = 'DELETE FROM ' . $t_filters_table . ' WHERE id=' . db_param();
  4158. $result = db_query_bound( $query, Array( $c_filter_id ) );
  4159. if( db_affected_rows( $result ) > 0 ) {
  4160. return true;
  4161. }
  4162. return false;
  4163. }
  4164. /**
  4165. * Delete all the unnamed filters
  4166. */
  4167. function filter_db_delete_current_filters() {
  4168. $t_filters_table = db_get_table( 'filters' );
  4169. $t_all_id = ALL_PROJECTS;
  4170. $query = "DELETE FROM $t_filters_table
  4171. WHERE project_id<=" . db_param() . "
  4172. AND name=" . db_param();
  4173. $result = db_query_bound( $query, Array( $t_all_id, '' ) );
  4174. }
  4175. /**
  4176. * @param int $p_project_id
  4177. * @param int $p_user_id
  4178. * @return mixed
  4179. */
  4180. function filter_db_get_available_queries( $p_project_id = null, $p_user_id = null ) {
  4181. $t_filters_table = db_get_table( 'filters' );
  4182. $t_overall_query_arr = array();
  4183. if( null === $p_project_id ) {
  4184. $t_project_id = helper_get_current_project();
  4185. } else {
  4186. $t_project_id = db_prepare_int( $p_project_id );
  4187. }
  4188. if( null === $p_user_id ) {
  4189. $t_user_id = auth_get_current_user_id();
  4190. } else {
  4191. $t_user_id = db_prepare_int( $p_user_id );
  4192. }
  4193. # If the user doesn't have access rights to stored queries, just return
  4194. if( !access_has_project_level( config_get( 'stored_query_use_threshold' ) ) ) {
  4195. return $t_overall_query_arr;
  4196. }
  4197. # Get the list of available queries. By sorting such that public queries are
  4198. # first, we can override any query that has the same name as a private query
  4199. # with that private one
  4200. $query = "SELECT * FROM $t_filters_table
  4201. WHERE (project_id=" . db_param() . "
  4202. OR project_id=0)
  4203. AND name!=''
  4204. ORDER BY is_public DESC, name ASC";
  4205. $result = db_query_bound( $query, Array( $t_project_id ) );
  4206. $query_count = db_num_rows( $result );
  4207. for( $i = 0;$i < $query_count;$i++ ) {
  4208. $row = db_fetch_array( $result );
  4209. if(( $row['user_id'] == $t_user_id ) || db_prepare_bool( $row['is_public'] ) ) {
  4210. $t_overall_query_arr[$row['id']] = $row['name'];
  4211. }
  4212. }
  4213. $t_overall_query_arr = array_unique( $t_overall_query_arr );
  4214. asort( $t_overall_query_arr );
  4215. return $t_overall_query_arr;
  4216. }
  4217. /**
  4218. * @param str $p_name
  4219. * @return bool true when under max_length (64) and false when over
  4220. */
  4221. function filter_name_valid_length( $p_name ) {
  4222. if( utf8_strlen( $p_name ) > 64 ) {
  4223. return false;
  4224. } else {
  4225. return true;
  4226. }
  4227. }