views_bonus_named_filters.module

Tracking 5.x-1.x branch
  1. drupal
    1. 5 contributions/views_bonus/views_bonus_named_filters/views_bonus_named_filters.module

Provides named versions of exposed views filters.

Example, instead of using http://example.com/myview?filter0=123456 you could use http://example.com/myview?timestamp=123456

Functions & methods

NameDescription
views_bonus_named_filters_admin_page
views_bonus_named_filters_editPage callback for modifying named filter settings for a view.
views_bonus_named_filters_edit_submitSubmit handler for views_bonus_named_filters form.
views_bonus_named_filters_menuImplementation of hook_menu().
views_bonus_named_filters_views_query_alterImplementation of hook_views_query_alter().
_views_bonus_named_filters_build_filtersRe-written version of _views_view_build_filters that doesn't add normal filters.
_views_bonus_named_filters_get_filtersGet a list of filter names for a given view.
_views_bonus_named_filters_named_filters_listBuilds a list of exposed filter names.
_views_bonus_named_filters_provides

File

View source
  1. <?php
  2. /**
  3. * @file
  4. * Provides named versions of exposed views filters.
  5. *
  6. * Example, instead of using http://example.com/myview?filter0=123456 you could
  7. * use http://example.com/myview?timestamp=123456
  8. */
  9. /**
  10. * Implementation of hook_menu().
  11. */
  12. function views_bonus_named_filters_menu($may_cache) {
  13. $items[] = array();
  14. if ($may_cache) {
  15. $items[] = array(
  16. 'path' => 'admin/build/views/defaultnamedfilters',
  17. 'title' => t('Named Filters'),
  18. 'callback' => 'views_bonus_named_filters_admin_page',
  19. 'access' => user_access('administer views'),
  20. 'type' => MENU_LOCAL_TASK,
  21. );
  22. }
  23. else {
  24. if (user_access('administer views') &&
  25. arg(0) == 'admin' &&
  26. arg(1) == 'build' &&
  27. arg(2) == 'views') {
  28. $view_name = arg(3);
  29. $default_view = false;
  30. if ($view_name && !($view = views_load_view($view_name))) {
  31. $view = views_get_view($view_name);
  32. $default_view = true;
  33. }
  34. if ($view && !empty($view->exposed_filter)) {
  35. $items[] = array(
  36. 'path' => "admin/build/views/$view->name/namedfilters",
  37. 'title' => t('Name Filters'),
  38. 'callback' => 'drupal_get_form',
  39. 'callback arguments' => array('views_bonus_named_filters_edit', $view->name),
  40. 'access' => user_access('administer views'),
  41. 'weight' => 10,
  42. 'type' => ($default_view ? MENU_CALLBACK : MENU_LOCAL_TASK),
  43. );
  44. }
  45. }
  46. }
  47. return $items;
  48. }
  49. /**
  50. *
  51. * @return unknown_type
  52. */
  53. function views_bonus_named_filters_admin_page() {
  54. views_load_cache();
  55. $numViews = 25;
  56. drupal_set_title(t('Administer views'));
  57. $result = pager_query("SELECT vid, name, description, menu_title, page_title, block_title, url, page, menu, block FROM {view_view} ORDER BY name", $numViews);
  58. while ($view = db_fetch_object($result)) {
  59. $url = ($view->page ? l($view->url, $view->url) : t('No Page View'));
  60. $provides = _views_bonus_named_filters_provides($view);
  61. $result2 = db_query("SELECT * FROM {view_exposed_filter} WHERE vid = $view->vid ORDER BY position ASC");
  62. $view->exposed_filter = array();
  63. while ($arg = db_fetch_array($result2)) {
  64. $arg['id'] = $arg['field'];
  65. $view->exposed_filter[] = $arg;
  66. }
  67. $items[] = array(
  68. $view->name,
  69. filter_xss_admin(views_get_title($view, 'admin')),
  70. $view->description,
  71. implode(', ', $provides),
  72. $url,
  73. _views_bonus_named_filters_named_filters_list($view),
  74. theme('links', array(
  75. array(
  76. 'title' => t('Manage Named Filters'),
  77. 'href' => "admin/build/views/$view->name/namedfilters",
  78. 'query' => drupal_get_destination(),
  79. ),
  80. )),
  81. );
  82. }
  83. if ($items) {
  84. $output = theme('table', array(t('View'), t('Title'), t('Description'), t('Provides'), t('URL'), t('Filters'), t('Actions')), $items, array("cellpadding" => "4"), t('Existing Views'));
  85. $output .= theme('pager', NULL, $numViews);
  86. }
  87. else {
  88. $output .= t('<p>No views have currently been defined.</p>');
  89. }
  90. $result = db_query("SELECT name FROM {view_view}");
  91. while ($view = db_fetch_object($result)) {
  92. $used[$view->name] = true;
  93. }
  94. $output .= t('<p>Below are system default views; if you edit one of these, a view will be created that will override any system use of the view.</p>');
  95. $items = array();
  96. $default_views = _views_get_default_views();
  97. $views_status = variable_get('views_defaults', array());
  98. foreach ($default_views as $view) {
  99. $url = ($view->page ? l($view->url, $view->url) : t('No Page View'));
  100. if ($used[$view->name]) {
  101. $status = t('Overridden');
  102. }
  103. else if (isset($views_status[$view->name])) {
  104. if ($views_status[$view->name] == 'enabled') {
  105. $status = t('Enabled');
  106. }
  107. else {
  108. $status = t('Disabled');
  109. }
  110. }
  111. else if ($view->disabled) {
  112. $status = t('Disabled');
  113. }
  114. else {
  115. $status = t('Enabled');
  116. }
  117. $provides = _views_bonus_named_filters_provides($view);
  118. $links = array(
  119. array(
  120. 'title' => t('Manage Named Filters'),
  121. 'href' => "admin/build/views/$view->name/namedfilters",
  122. 'query' => drupal_get_destination(),
  123. ),
  124. );
  125. $items[] = array(
  126. $view->name,
  127. filter_xss_admin(views_get_title($view, 'menu')),
  128. $view->description,
  129. implode(', ', $provides),
  130. $url,
  131. $status,
  132. _views_bonus_named_filters_named_filters_list($view),
  133. theme('links', $links),
  134. );
  135. }
  136. if ($items) {
  137. $output .= theme('table', array(t('Default view'), t('Title'), t('Description'), t('Provides'), t('URL'), t('Status'), t('Filters'), t('Named Filters')), $items, array("cellpadding" => "4"), t('Default Views'));
  138. }
  139. else {
  140. $output .= t('<p>No views have currently been defined.</p>');
  141. }
  142. return $output;
  143. }
  144. function _views_bonus_named_filters_provides(&$view) {
  145. $provides = array();
  146. if ($view->page) {
  147. $provides[] = t('Page');
  148. }
  149. if ($view->block) {
  150. $provides[] = t('Block');
  151. }
  152. if ($view->menu) {
  153. $provides[] = t('Menu');
  154. }
  155. return $provides;
  156. }
  157. /**
  158. * Builds a list of exposed filter names.
  159. *
  160. * @param $view
  161. * View to build a list of filters for.
  162. * @return
  163. * A themed table of exposed filter names.
  164. */
  165. function _views_bonus_named_filters_named_filters_list(&$view) {
  166. $named_filters = _views_bonus_named_filters_get_filters($view->name);
  167. $rows = array();
  168. foreach ($view->exposed_filter as $position => $filter) {
  169. $row = array();
  170. $row[] = "filter$position";
  171. foreach ($named_filters as $named_position => $named_filter) {
  172. if ($named_position == $position) {
  173. $row[] = $named_filter->filter_name;
  174. break;
  175. }
  176. }
  177. if (sizeof($row) == 1) {
  178. $row[] = '';
  179. }
  180. $rows[] = $row;
  181. }
  182. if (!empty($rows[0])) {
  183. return theme('table', array(t('Exposed'), t('Named')), $rows);
  184. }
  185. }
  186. /**
  187. * Page callback for modifying named filter settings for a view.
  188. *
  189. * @param $view_name
  190. * The name of a view to add named filter settings for.
  191. * @return
  192. * FAPI array.
  193. */
  194. function views_bonus_named_filters_edit($view_name) {
  195. $form = array();
  196. $view = views_get_view($view_name);
  197. $filters = _views_get_filters();
  198. $named_filters = _views_bonus_named_filters_get_filters($view->name);
  199. $form['view'] = array(
  200. '#type' => 'value',
  201. '#value' => $view,
  202. );
  203. $form['filters']['#tree'] = TRUE;
  204. foreach ($view->exposed_filter as $position => $field) {
  205. $section = array();
  206. $filtername = $field['id'];
  207. $filterinfo = $filters[$filtername];
  208. $section['name'] = array(
  209. '#type' => 'textfield',
  210. '#title' => t('Name'),
  211. '#size' => 25,
  212. '#default_value' => $named_filters[$position]->filter_name,
  213. );
  214. if (!isset($form['filters'][$filtername])) {
  215. $form['filters'][$filtername] = array(
  216. '#type' => 'fieldset',
  217. '#title' => $filterinfo['name'],
  218. '#tree' => true,
  219. );
  220. }
  221. $form['filters'][$filtername][$position] = $section;
  222. }
  223. $form['submit'] = array(
  224. '#type' => 'submit',
  225. '#value' => 'Submit',
  226. );
  227. return $form;
  228. }
  229. /**
  230. * Submit handler for views_bonus_named_filters form.
  231. *
  232. * Save named filter choices into the database.
  233. * @return
  234. * We don't care about where the redirect goes so no return value.
  235. */
  236. function views_bonus_named_filters_edit_submit($form_id, $form_values) {
  237. db_query("DELETE FROM {views_bonus_named_filters} WHERE view_name = '%s'", $form_values['view']->name);
  238. foreach ($form_values['filters'] as $id => $filters) {
  239. foreach ($filters as $position => $filter) {
  240. if ($filter['name']) {
  241. db_query("INSERT INTO {views_bonus_named_filters} (filter_name, filter_id, view_name, position) VALUES ('%s', '%s', '%s', %d)",
  242. $filter['name'], $id, $form_values['view']->name, $position);
  243. }
  244. }
  245. }
  246. cache_clear_all('views_filter_names:' . $form_values['view']->name, 'cache_views');
  247. }
  248. /**
  249. * Implementation of hook_views_query_alter().
  250. */
  251. function views_bonus_named_filters_views_query_alter(&$query, &$view, $summary, $level) {
  252. // See if this view has any named filters
  253. $named_filters = _views_bonus_named_filters_get_filters($view->name);
  254. if (!empty($named_filters)) {
  255. $values = array();
  256. // Look through our named filters.
  257. foreach ($named_filters as $position => $filter) {
  258. if ($value = $_GET[$filter->filter_name]) {
  259. // So, we found a filter. Add it to the running list to pass to views.
  260. $values[$position]['filter'] = $value;
  261. }
  262. }
  263. // If we found exposed arguments, tell views to update the filters.
  264. if (!empty($values)) {
  265. _views_bonus_named_filters_build_filters($query, $view, $values);
  266. }
  267. }
  268. }
  269. /**
  270. * Re-written version of _views_view_build_filters that doesn't add normal filters.
  271. *
  272. * Supports handling multiple exposed arguments of the same type a little bit
  273. * better than _views_view_build_filters does as well.
  274. */
  275. function _views_bonus_named_filters_build_filters(&$query, &$view, $exposed_filter_values) {
  276. $filters = _views_get_filters();
  277. $view->used_filters = array();
  278. $exposed_filters = $view->exposed_filter;
  279. foreach ($view->filter as $i => $filter) {
  280. $filterinfo = $filters[$filter['field']]; // shortcut
  281. if (!$filterinfo['field']) {
  282. $fieldbits = explode('.', $filter['field']);
  283. $filterinfo['field'] = $fieldbits[1];
  284. }
  285. foreach($exposed_filters as $position => $expose) {
  286. if ($filter['id'] == $expose['id'] && empty($exposed_filters[$position]['filterinfo'])) {
  287. $id = $expose['id'];
  288. /**
  289. * This is the part that's different from views. Instead of breaking
  290. * executing the following code for all views, we just execute it here.
  291. */
  292. $replace = array('&gt;' => '>', '&lt;' => '<');
  293. $filter['operator'] = strtr($filter['operator'], $replace);
  294. // Stash values for later.
  295. $exposed_filters[$position]['filterinfo'] = $filterinfo;
  296. $exposed_filters[$position]['filter'] = $filter;
  297. // We found an exposed filter and setup the values so now we drop out
  298. // to the normal filter loop so we can find the next one.
  299. break;
  300. }
  301. }
  302. }
  303. foreach ($exposed_filters as $position => $expose) {
  304. /**
  305. * No op support yet.
  306. *
  307. if (!$expose['operator'] && $exposed_filter_values[$count]['op']) {
  308. $filter['operator'] = check_plain($exposed_filter_values[$count]['op']);
  309. $view->used_filters["op$count"] = $exposed_filter_values[$count]['op'];
  310. }
  311. */
  312. // Pull values back out of exposed array.
  313. $filter = $expose['filter'];
  314. $filterinfo = $expose['filterinfo'];
  315. // If its optional there's a little bit different logic. Skip processing
  316. // in a couple cases.
  317. if ($expose['optional']) {
  318. if ((!isset($exposed_filter_values[$position]['filter']) || $exposed_filter_values[$position]['filter'] == '') && !$expose['is_default']) {
  319. continue; // skip
  320. }
  321. if ($exposed_filter_values[$position]['filter'] == '**ALL**' ||
  322. (is_array($exposed_filter_values[$position]['filter']) && in_array('**ALL**', $exposed_filter_values[$position]['filter']))) {
  323. $view->used_filters["filter$position"] = $exposed_filter_values[$position]['filter'];
  324. continue; // skip this filter entirely.
  325. }
  326. }
  327. // If there's an exposed value, for the given filter, set it up.
  328. if (isset($exposed_filter_values[$position]['filter']) && $exposed_filter_values[$position]['filter'] != '') {
  329. $value = $exposed_filter_values[$position]['filter'];
  330. if ($filterinfo['value-type'] == 'array' && !is_array($value)) {
  331. $value = array($value);
  332. }
  333. $filter['value'] = $value;
  334. $view->used_filters["filter$position"] = $exposed_filter_values[$position]['filter'];
  335. }
  336. // Double check that we've got a valid handler and fall back on the default.
  337. if (!function_exists($filterinfo['handler'])) {
  338. $filterinfo['handler'] = 'views_handler_filter_default';
  339. }
  340. // Fire of our handler to take care of the rest.
  341. $filterinfo['handler']('handler', $filter, $filterinfo, $query);
  342. }
  343. }
  344. /**
  345. * Get a list of filter names for a given view.
  346. *
  347. * This gets called for every view so we cache the views to limit the impact
  348. * on views loading.
  349. *
  350. * @param $view_name
  351. * The name of the view to get a list for.
  352. * @return
  353. * An array of named filters for a view. Empty if non found.
  354. */
  355. function _views_bonus_named_filters_get_filters($view_name) {
  356. $filters = array();
  357. if ($cached = cache_get('views_filter_names:' . $view_name, 'cache_views')) {
  358. $filters = $cached->data;
  359. }
  360. elseif ($result = db_query("SELECT filter_id, filter_name, position FROM {views_bonus_named_filters} WHERE view_name = '%s'", $view_name)) {
  361. while ($row = db_fetch_object($result)) {
  362. $filters[$row->position] = $row;
  363. }
  364. cache_set('views_filter_names:' . $view_name, 'cache_views', $filters);
  365. }
  366. return $filters;
  367. }