[177a560] | 1 | <?php |
---|
| 2 | |
---|
| 3 | /** |
---|
| 4 | * @file |
---|
| 5 | * Defines date-related Views data and plugins: |
---|
| 6 | * |
---|
| 7 | * Date argument: |
---|
| 8 | * A generic date argument that has an option to select one or more |
---|
| 9 | * Views date fields to filter on, automatically adds them to the view, |
---|
| 10 | * and then filters the view by the value of the selected field(s). |
---|
| 11 | * The flexible argument will accept and evaluate most ISO date |
---|
| 12 | * and period formats, like 2009-05-01, 2008-W25, P1W. |
---|
| 13 | * |
---|
| 14 | * Date filter: |
---|
| 15 | * A generic date filter that has an option to select a |
---|
| 16 | * Views date field to filter on, with a choice of a widget to use |
---|
| 17 | * for the filter form and an option to set the default value to |
---|
| 18 | * a set date or something like 'now +90 days'. If the operator is |
---|
| 19 | * set to 'between' or 'not between' you can set a default value for |
---|
| 20 | * both the from and to dates. |
---|
| 21 | * |
---|
| 22 | * Current date argument default |
---|
| 23 | * Adds a default option to set the argument to the current date |
---|
| 24 | * when the argument is empty. |
---|
| 25 | * |
---|
| 26 | * Date navigation attachment |
---|
| 27 | * Navigation that can be attached to any display to create back/next |
---|
| 28 | * links by date, requires the date argument and uses the current |
---|
| 29 | * date argument default to set a starting point for the view. |
---|
| 30 | */ |
---|
| 31 | /** |
---|
| 32 | * Implementation of hook_views_handlers() to register all of the basic handlers |
---|
| 33 | * views uses. |
---|
| 34 | */ |
---|
| 35 | function date_api_views_handlers() { |
---|
| 36 | return array( |
---|
| 37 | 'info' => array( |
---|
| 38 | 'path' => drupal_get_path('module', 'date_api') .'/includes', |
---|
| 39 | ), |
---|
| 40 | 'handlers' => array( |
---|
| 41 | 'date_api_argument_handler' => array( |
---|
| 42 | 'parent' => 'views_handler_argument_date', |
---|
| 43 | ), |
---|
| 44 | 'date_api_filter_handler' => array( |
---|
| 45 | 'parent' => 'views_handler_filter_numeric', |
---|
| 46 | ), |
---|
| 47 | ), |
---|
| 48 | ); |
---|
| 49 | } |
---|
| 50 | |
---|
| 51 | /** |
---|
| 52 | * Implementation of hook_views_plugins(). |
---|
| 53 | */ |
---|
| 54 | function date_api_views_plugins() { |
---|
| 55 | $path = drupal_get_path('module', 'date_api'); |
---|
| 56 | $views_path = drupal_get_path('module', 'views'); |
---|
| 57 | require_once "./$path/theme/theme.inc"; |
---|
| 58 | return array( |
---|
| 59 | 'module' => 'date_api', // This just tells our themes are elsewhere. |
---|
| 60 | 'display' => array( |
---|
| 61 | // Parents are not really displays, just needed so the files can |
---|
| 62 | // be included. |
---|
| 63 | 'parent' => array( |
---|
| 64 | 'no ui' => TRUE, |
---|
| 65 | 'handler' => 'views_plugin_display', |
---|
| 66 | 'path' => "$views_path/plugins", |
---|
| 67 | 'parent' => '', |
---|
| 68 | ), |
---|
| 69 | 'attachment' => array( |
---|
| 70 | 'no ui' => TRUE, |
---|
| 71 | 'handler' => 'views_plugin_display_attachment', |
---|
| 72 | 'path' => "$views_path/plugins", |
---|
| 73 | 'parent' => 'parent', |
---|
| 74 | ), |
---|
| 75 | // Display plugin for date navigation. |
---|
| 76 | 'date_nav' => array( |
---|
| 77 | 'title' => t('Date browser'), |
---|
| 78 | 'help' => t('Date back/next navigation to attach to other displays. Requires the Date argument.'), |
---|
| 79 | 'handler' => 'date_plugin_display_attachment', |
---|
| 80 | 'parent' => 'attachment', |
---|
| 81 | 'path' => "$path/includes", |
---|
| 82 | 'theme' => 'views_view', |
---|
| 83 | 'use ajax' => TRUE, |
---|
| 84 | 'admin' => t('Date browser'), |
---|
| 85 | 'help topic' => 'date-browser', |
---|
| 86 | ), |
---|
| 87 | ), |
---|
| 88 | 'style' => array( |
---|
| 89 | 'parent' => array( |
---|
| 90 | // this isn't really a display but is necessary so the file can |
---|
| 91 | // be included. |
---|
| 92 | 'no ui' => TRUE, |
---|
| 93 | 'handler' => 'views_plugin_style', |
---|
| 94 | 'path' => "$views_path/plugins", |
---|
| 95 | 'theme file' => 'theme.inc', |
---|
| 96 | 'theme path' => "$views_path/theme", |
---|
| 97 | 'parent' => '', |
---|
| 98 | ), |
---|
| 99 | 'date_nav' => array( |
---|
| 100 | 'title' => t('Date browser style'), |
---|
| 101 | 'help' => t('Creates back/next navigation.'), |
---|
| 102 | 'handler' => 'date_navigation_plugin_style', |
---|
| 103 | 'path' => "$path/includes", |
---|
| 104 | 'parent' => 'parent', |
---|
| 105 | 'theme' => 'date_navigation', |
---|
| 106 | 'theme file' => 'theme.inc', |
---|
| 107 | 'theme path' => "$path/theme", |
---|
| 108 | 'uses row plugin' => FALSE, |
---|
| 109 | 'uses fields' => FALSE, |
---|
| 110 | 'uses options' => TRUE, |
---|
| 111 | 'type' => 'date_nav', |
---|
| 112 | 'even empty' => TRUE, |
---|
| 113 | ), |
---|
| 114 | ), |
---|
| 115 | ); |
---|
| 116 | } |
---|
| 117 | |
---|
| 118 | /** |
---|
| 119 | * Implementation of hook_views_data(). |
---|
| 120 | */ |
---|
| 121 | function date_api_views_data() { |
---|
| 122 | $data = array(); |
---|
| 123 | |
---|
| 124 | $tables = module_invoke_all('date_api_tables'); |
---|
| 125 | |
---|
| 126 | foreach ($tables as $base_table) { |
---|
| 127 | // The flexible date argument. |
---|
| 128 | $data[$base_table]['date_argument'] = array( |
---|
| 129 | 'group' => t('Date'), |
---|
| 130 | 'title' => t('Date (!base_table)', array('!base_table' => $base_table)), |
---|
| 131 | 'help' => t('Filter any Views !base_table date field by a date argument, using any common ISO date/period format (i.e. YYYY, YYYY-MM, YYYY-MM-DD, YYYY-W99, YYYY-MM-DD--P3M, P90D, etc).', array('!base_table' => $base_table)), |
---|
| 132 | 'argument' => array( |
---|
| 133 | 'handler' => 'date_api_argument_handler', |
---|
| 134 | 'empty field name' => t('Undated'), |
---|
| 135 | 'base' => $base_table, |
---|
| 136 | ), |
---|
| 137 | ); |
---|
| 138 | // The flexible date filter. |
---|
| 139 | $data[$base_table]['date_filter'] = array( |
---|
| 140 | 'group' => t('Date'), |
---|
| 141 | 'title' => t('Date (!base_table)', array('!base_table' => $base_table)), |
---|
| 142 | 'help' => t('Filter any Views !base_table date field.', array('!base_table' => $base_table)), |
---|
| 143 | 'filter' => array( |
---|
| 144 | 'handler' => 'date_api_filter_handler', |
---|
| 145 | 'empty field name' => t('Undated'), |
---|
| 146 | 'base' => $base_table, |
---|
| 147 | ), |
---|
| 148 | ); |
---|
| 149 | } |
---|
| 150 | return $data; |
---|
| 151 | } |
---|
| 152 | |
---|
| 153 | /** |
---|
| 154 | * Identify all potential date/timestamp fields and cache the data. |
---|
| 155 | */ |
---|
| 156 | function date_api_fields($base = 'node', $reset = FALSE) { |
---|
| 157 | static $fields = array(); |
---|
| 158 | $empty = array('name' => array(), 'alias' => array()); |
---|
| 159 | require_once('./'. drupal_get_path('module', 'date_api') .'/includes/date_api_fields.inc'); |
---|
| 160 | if (empty($fields[$base]) || $reset) { |
---|
| 161 | $cid = 'date_api_fields_'. $base; |
---|
| 162 | if (!$reset && $cached = cache_get($cid, 'cache_views')) { |
---|
| 163 | $fields[$base] = $cached->data; |
---|
| 164 | } |
---|
| 165 | else { |
---|
| 166 | $fields[$base] = _date_api_fields($base); |
---|
| 167 | } |
---|
| 168 | } |
---|
| 169 | // Make sure that empty values will be arrays in he expected format. |
---|
| 170 | return !empty($fields) && !empty($fields[$base]) ? $fields[$base] : $empty; |
---|
| 171 | } |
---|
| 172 | |
---|
| 173 | /** |
---|
| 174 | * Central function for setting up the right timezone values |
---|
| 175 | * in the SQL date handler. |
---|
| 176 | * |
---|
| 177 | * The date handler will use this information to decide if the |
---|
| 178 | * database value needs a timezone conversion. |
---|
| 179 | * |
---|
| 180 | * In Views, we will always be comparing to a local date value, |
---|
| 181 | * so the goal is to convert the database value to the right |
---|
| 182 | * value to compare to the local value. |
---|
| 183 | */ |
---|
| 184 | function date_views_set_timezone(&$date_handler, &$view, $field) { |
---|
| 185 | $tz_handling = $field['tz_handling']; |
---|
| 186 | switch ($tz_handling) { |
---|
| 187 | case 'date' : |
---|
| 188 | $date_handler->db_timezone = 'UTC'; |
---|
| 189 | $date_handler->local_timezone_field = $field['timezone_field']; |
---|
| 190 | $date_handler->offset_field = $field['offset_field']; |
---|
| 191 | break; |
---|
| 192 | case 'none': |
---|
| 193 | $date_handler->db_timezone = date_default_timezone_name(); |
---|
| 194 | $date_handler->local_timezone = date_default_timezone_name(); |
---|
| 195 | break; |
---|
| 196 | case 'utc': |
---|
| 197 | $date_handler->db_timezone = 'UTC'; |
---|
| 198 | $date_handler->local_timezone = 'UTC'; |
---|
| 199 | break; |
---|
| 200 | default : |
---|
| 201 | $date_handler->db_timezone = 'UTC'; |
---|
| 202 | $date_handler->local_timezone = date_default_timezone_name(); |
---|
| 203 | break; |
---|
| 204 | } |
---|
| 205 | } |
---|
| 206 | |
---|
| 207 | function date_views_querystring($view, $extra_params = array()) { |
---|
| 208 | $query_params = array_merge($_GET, $extra_params); |
---|
| 209 | // Allow NULL params to be removed from the query string. |
---|
| 210 | foreach ($extra_params AS $key => $value) { |
---|
| 211 | if (!isset($value)) { |
---|
| 212 | unset($query_params[$key]); |
---|
| 213 | } |
---|
| 214 | } |
---|
| 215 | // Filter the special "q" and "view" variables out of the query string. |
---|
| 216 | $exclude = array('q'); |
---|
| 217 | // If we don't explicitly add a value for "view", filter it out. |
---|
| 218 | if (empty($extra_params['view'])) { |
---|
| 219 | $exclude[] = 'view'; |
---|
| 220 | } |
---|
| 221 | $query = drupal_query_string_encode($query_params, $exclude); |
---|
| 222 | // To prevent an empty query string from adding a "?" on to the end of a URL, |
---|
| 223 | // we return NULL. |
---|
| 224 | return !empty($query) ? $query : NULL; |
---|
| 225 | } |
---|
| 226 | |
---|
| 227 | /** |
---|
| 228 | * Identify the base url of the page, |
---|
| 229 | * needed when the calendar is embedded so we |
---|
| 230 | * don't set the url to the calendar url. |
---|
| 231 | */ |
---|
| 232 | function date_views_page_url($view) { |
---|
| 233 | if ($view->build_type == 'page') { |
---|
| 234 | return date_views_real_url($view, $view->date_info->real_args); |
---|
| 235 | } |
---|
| 236 | else { |
---|
| 237 | $block_identifier = isset($view->date_info->block_identifier) ? $view->date_info->block_identifier : 'mini'; |
---|
| 238 | return url($_GET['q'], date_views_querystring($view, array($block_identifier => NULL)), NULL, TRUE); |
---|
| 239 | } |
---|
| 240 | } |
---|
| 241 | |
---|
| 242 | /** |
---|
| 243 | * Figure out what the URL of the calendar view we're currently looking at is. |
---|
| 244 | */ |
---|
| 245 | function date_views_real_url($view, $args) { |
---|
| 246 | if (empty($args)) { |
---|
| 247 | return $view->date_info->url; |
---|
| 248 | } |
---|
| 249 | // Add non-calendar arguments to the base url. |
---|
| 250 | $parts = explode('/', $view->date_info->url); |
---|
| 251 | $bump = 0; |
---|
| 252 | foreach ($parts as $delta => $part) { |
---|
| 253 | // If one of the args is buried in the url, add it here and adjust |
---|
| 254 | // the delta values we'll compare the calendar arg positions to. |
---|
| 255 | if (drupal_substr($part, 0, 1) == '$') { |
---|
| 256 | $parts[$delta] = array_shift($args); |
---|
| 257 | $bump++; |
---|
| 258 | } |
---|
| 259 | } |
---|
| 260 | foreach ($args as $delta => $arg) { |
---|
| 261 | if (!in_array($delta + $bump, calendar_arg_positions($view)) && !empty($arg)) { |
---|
| 262 | array_push($parts, $arg); |
---|
| 263 | } |
---|
| 264 | } |
---|
| 265 | return implode('/', $parts); |
---|
| 266 | } |
---|