1 | <?php |
---|
2 | |
---|
3 | /** |
---|
4 | * @file |
---|
5 | * Admin page callbacks for the aggregator module. |
---|
6 | */ |
---|
7 | |
---|
8 | /** |
---|
9 | * Menu callback; displays the aggregator administration page. |
---|
10 | */ |
---|
11 | function aggregator_admin_overview() { |
---|
12 | return aggregator_view(); |
---|
13 | } |
---|
14 | |
---|
15 | /** |
---|
16 | * Displays the aggregator administration page. |
---|
17 | * |
---|
18 | * @return |
---|
19 | * The page HTML. |
---|
20 | */ |
---|
21 | function aggregator_view() { |
---|
22 | $result = db_query('SELECT f.*, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.etag, f.modified, f.image, f.block ORDER BY f.title'); |
---|
23 | |
---|
24 | $output = '<h3>'. t('Feed overview') .'</h3>'; |
---|
25 | |
---|
26 | $header = array(t('Title'), t('Items'), t('Last update'), t('Next update'), array('data' => t('Operations'), 'colspan' => '3')); |
---|
27 | $rows = array(); |
---|
28 | while ($feed = db_fetch_object($result)) { |
---|
29 | $rows[] = array( |
---|
30 | l($feed->title, "aggregator/sources/$feed->fid"), |
---|
31 | format_plural($feed->items, '1 item', '@count items'), |
---|
32 | ($feed->checked ? t('@time ago', array('@time' => format_interval(time() - $feed->checked))) : t('never')), |
---|
33 | ($feed->checked ? t('%time left', array('%time' => format_interval($feed->checked + $feed->refresh - time()))) : t('never')), |
---|
34 | l(t('edit'), "admin/content/aggregator/edit/feed/$feed->fid"), |
---|
35 | l(t('remove items'), "admin/content/aggregator/remove/$feed->fid"), |
---|
36 | l(t('update items'), "admin/content/aggregator/update/$feed->fid", array('query' => array('token' => drupal_get_token("aggregator/update/$feed->fid")))), |
---|
37 | ); |
---|
38 | } |
---|
39 | $output .= theme('table', $header, $rows); |
---|
40 | |
---|
41 | $result = db_query('SELECT c.cid, c.title, count(ci.iid) as items FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid GROUP BY c.cid, c.title ORDER BY title'); |
---|
42 | |
---|
43 | $output .= '<h3>'. t('Category overview') .'</h3>'; |
---|
44 | |
---|
45 | $header = array(t('Title'), t('Items'), t('Operations')); |
---|
46 | $rows = array(); |
---|
47 | while ($category = db_fetch_object($result)) { |
---|
48 | $rows[] = array(l($category->title, "aggregator/categories/$category->cid"), format_plural($category->items, '1 item', '@count items'), l(t('edit'), "admin/content/aggregator/edit/category/$category->cid")); |
---|
49 | } |
---|
50 | $output .= theme('table', $header, $rows); |
---|
51 | |
---|
52 | return $output; |
---|
53 | } |
---|
54 | |
---|
55 | /** |
---|
56 | * Form builder; Generate a form to add/edit feed sources. |
---|
57 | * |
---|
58 | * @ingroup forms |
---|
59 | * @see aggregator_form_feed_validate() |
---|
60 | * @see aggregator_form_feed_submit() |
---|
61 | */ |
---|
62 | function aggregator_form_feed(&$form_state, $edit = array('refresh' => 900, 'title' => '', 'url' => '', 'fid' => NULL)) { |
---|
63 | $period = drupal_map_assoc(array(900, 1800, 3600, 7200, 10800, 21600, 32400, 43200, 64800, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); |
---|
64 | |
---|
65 | if ($edit['refresh'] == '') { |
---|
66 | $edit['refresh'] = 3600; |
---|
67 | } |
---|
68 | |
---|
69 | $form['title'] = array('#type' => 'textfield', |
---|
70 | '#title' => t('Title'), |
---|
71 | '#default_value' => $edit['title'], |
---|
72 | '#maxlength' => 255, |
---|
73 | '#description' => t('The name of the feed (or the name of the website providing the feed).'), |
---|
74 | '#required' => TRUE, |
---|
75 | ); |
---|
76 | $form['url'] = array('#type' => 'textfield', |
---|
77 | '#title' => t('URL'), |
---|
78 | '#default_value' => $edit['url'], |
---|
79 | '#maxlength' => 255, |
---|
80 | '#description' => t('The fully-qualified URL of the feed.'), |
---|
81 | '#required' => TRUE, |
---|
82 | ); |
---|
83 | $form['refresh'] = array('#type' => 'select', |
---|
84 | '#title' => t('Update interval'), |
---|
85 | '#default_value' => $edit['refresh'], |
---|
86 | '#options' => $period, |
---|
87 | '#description' => t('The length of time between feed updates. (Requires a correctly configured <a href="@cron">cron maintenance task</a>.)', array('@cron' => url('admin/reports/status'))), |
---|
88 | ); |
---|
89 | |
---|
90 | // Handling of categories: |
---|
91 | $options = array(); |
---|
92 | $values = array(); |
---|
93 | $categories = db_query('SELECT c.cid, c.title, f.fid FROM {aggregator_category} c LEFT JOIN {aggregator_category_feed} f ON c.cid = f.cid AND f.fid = %d ORDER BY title', $edit['fid']); |
---|
94 | while ($category = db_fetch_object($categories)) { |
---|
95 | $options[$category->cid] = check_plain($category->title); |
---|
96 | if ($category->fid) $values[] = $category->cid; |
---|
97 | } |
---|
98 | if ($options) { |
---|
99 | $form['category'] = array('#type' => 'checkboxes', |
---|
100 | '#title' => t('Categorize news items'), |
---|
101 | '#default_value' => $values, |
---|
102 | '#options' => $options, |
---|
103 | '#description' => t('New feed items are automatically filed in the checked categories.'), |
---|
104 | ); |
---|
105 | } |
---|
106 | $form['submit'] = array('#type' => 'submit', '#value' => t('Save')); |
---|
107 | |
---|
108 | if ($edit['fid']) { |
---|
109 | $form['delete'] = array('#type' => 'submit', '#value' => t('Delete')); |
---|
110 | $form['fid'] = array('#type' => 'hidden', '#value' => $edit['fid']); |
---|
111 | } |
---|
112 | |
---|
113 | return $form; |
---|
114 | } |
---|
115 | |
---|
116 | /** |
---|
117 | * Validate aggregator_form_feed form submissions. |
---|
118 | */ |
---|
119 | function aggregator_form_feed_validate($form, &$form_state) { |
---|
120 | if ($form_state['values']['op'] == t('Save')) { |
---|
121 | // Ensure URL is valid. |
---|
122 | if (!valid_url($form_state['values']['url'], TRUE)) { |
---|
123 | form_set_error('url', t('The URL %url is invalid. Please enter a fully-qualified URL, such as http://www.example.com/feed.xml.', array('%url' => $form_state['values']['url']))); |
---|
124 | } |
---|
125 | // Check for duplicate titles. |
---|
126 | if (isset($form_state['values']['fid'])) { |
---|
127 | $result = db_query("SELECT title, url FROM {aggregator_feed} WHERE (title = '%s' OR url = '%s') AND fid <> %d", $form_state['values']['title'], $form_state['values']['url'], $form_state['values']['fid']); |
---|
128 | } |
---|
129 | else { |
---|
130 | $result = db_query("SELECT title, url FROM {aggregator_feed} WHERE title = '%s' OR url = '%s'", $form_state['values']['title'], $form_state['values']['url']); |
---|
131 | } |
---|
132 | while ($feed = db_fetch_object($result)) { |
---|
133 | if (strcasecmp($feed->title, $form_state['values']['title']) == 0) { |
---|
134 | form_set_error('title', t('A feed named %feed already exists. Please enter a unique title.', array('%feed' => $form_state['values']['title']))); |
---|
135 | } |
---|
136 | if (strcasecmp($feed->url, $form_state['values']['url']) == 0) { |
---|
137 | form_set_error('url', t('A feed with this URL %url already exists. Please enter a unique URL.', array('%url' => $form_state['values']['url']))); |
---|
138 | } |
---|
139 | } |
---|
140 | } |
---|
141 | } |
---|
142 | |
---|
143 | /** |
---|
144 | * Process aggregator_form_feed form submissions. |
---|
145 | * |
---|
146 | * @todo Add delete confirmation dialog. |
---|
147 | */ |
---|
148 | function aggregator_form_feed_submit($form, &$form_state) { |
---|
149 | if ($form_state['values']['op'] == t('Delete')) { |
---|
150 | $title = $form_state['values']['title']; |
---|
151 | // Unset the title: |
---|
152 | unset($form_state['values']['title']); |
---|
153 | } |
---|
154 | aggregator_save_feed($form_state['values']); |
---|
155 | if (isset($form_state['values']['fid'])) { |
---|
156 | if (isset($form_state['values']['title'])) { |
---|
157 | drupal_set_message(t('The feed %feed has been updated.', array('%feed' => $form_state['values']['title']))); |
---|
158 | if (arg(0) == 'admin') { |
---|
159 | $form_state['redirect'] = 'admin/content/aggregator/'; |
---|
160 | return; |
---|
161 | } |
---|
162 | else { |
---|
163 | $form_state['redirect'] = 'aggregator/sources/'. $form_state['values']['fid']; |
---|
164 | return; |
---|
165 | } |
---|
166 | } |
---|
167 | else { |
---|
168 | watchdog('aggregator', 'Feed %feed deleted.', array('%feed' => $title)); |
---|
169 | drupal_set_message(t('The feed %feed has been deleted.', array('%feed' => $title))); |
---|
170 | if (arg(0) == 'admin') { |
---|
171 | $form_state['redirect'] = 'admin/content/aggregator/'; |
---|
172 | return; |
---|
173 | } |
---|
174 | else { |
---|
175 | $form_state['redirect'] = 'aggregator/sources/'; |
---|
176 | return; |
---|
177 | } |
---|
178 | } |
---|
179 | } |
---|
180 | else { |
---|
181 | watchdog('aggregator', 'Feed %feed added.', array('%feed' => $form_state['values']['title']), WATCHDOG_NOTICE, l(t('view'), 'admin/content/aggregator')); |
---|
182 | drupal_set_message(t('The feed %feed has been added.', array('%feed' => $form_state['values']['title']))); |
---|
183 | } |
---|
184 | } |
---|
185 | |
---|
186 | function aggregator_admin_remove_feed($form_state, $feed) { |
---|
187 | return confirm_form( |
---|
188 | array( |
---|
189 | 'feed' => array( |
---|
190 | '#type' => 'value', |
---|
191 | '#value' => $feed, |
---|
192 | ), |
---|
193 | ), |
---|
194 | t('Are you sure you want to remove all items from the feed %feed?', array('%feed' => $feed['title'])), |
---|
195 | 'admin/content/aggregator', |
---|
196 | t('This action cannot be undone.'), |
---|
197 | t('Remove items'), |
---|
198 | t('Cancel') |
---|
199 | ); |
---|
200 | } |
---|
201 | |
---|
202 | /** |
---|
203 | * Remove all items from a feed and redirect to the overview page. |
---|
204 | * |
---|
205 | * @param $feed |
---|
206 | * An associative array describing the feed to be cleared. |
---|
207 | */ |
---|
208 | function aggregator_admin_remove_feed_submit($form, &$form_state) { |
---|
209 | aggregator_remove($form_state['values']['feed']); |
---|
210 | $form_state['redirect'] = 'admin/content/aggregator'; |
---|
211 | } |
---|
212 | |
---|
213 | /** |
---|
214 | * Menu callback; refreshes a feed, then redirects to the overview page. |
---|
215 | * |
---|
216 | * @param $feed |
---|
217 | * An associative array describing the feed to be refreshed. |
---|
218 | */ |
---|
219 | function aggregator_admin_refresh_feed($feed) { |
---|
220 | if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], 'aggregator/update/' . $feed['fid'])) { |
---|
221 | return drupal_access_denied(); |
---|
222 | } |
---|
223 | aggregator_refresh($feed); |
---|
224 | drupal_goto('admin/content/aggregator'); |
---|
225 | } |
---|
226 | |
---|
227 | /** |
---|
228 | * Form builder; Configure the aggregator system. |
---|
229 | * |
---|
230 | * @ingroup forms |
---|
231 | * @see system_settings_form() |
---|
232 | */ |
---|
233 | function aggregator_admin_settings() { |
---|
234 | $items = array(0 => t('none')) + drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items'); |
---|
235 | $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval'); |
---|
236 | |
---|
237 | $form['aggregator_allowed_html_tags'] = array( |
---|
238 | '#type' => 'textfield', '#title' => t('Allowed HTML tags'), '#size' => 80, '#maxlength' => 255, |
---|
239 | '#default_value' => variable_get('aggregator_allowed_html_tags', '<a> <b> <br> <dd> <dl> <dt> <em> <i> <li> <ol> <p> <strong> <u> <ul>'), |
---|
240 | '#description' => t('A space-separated list of HTML tags allowed in the content of feed items. (Tags in this list are not removed by Drupal.)') |
---|
241 | ); |
---|
242 | |
---|
243 | $form['aggregator_summary_items'] = array( |
---|
244 | '#type' => 'select', '#title' => t('Items shown in sources and categories pages') , |
---|
245 | '#default_value' => variable_get('aggregator_summary_items', 3), '#options' => $items, |
---|
246 | '#description' => t('Number of feed items displayed in feed and category summary pages.') |
---|
247 | ); |
---|
248 | |
---|
249 | $form['aggregator_clear'] = array( |
---|
250 | '#type' => 'select', '#title' => t('Discard items older than'), |
---|
251 | '#default_value' => variable_get('aggregator_clear', 9676800), '#options' => $period, |
---|
252 | '#description' => t('The length of time to retain feed items before discarding. (Requires a correctly configured <a href="@cron">cron maintenance task</a>.)', array('@cron' => url('admin/reports/status'))) |
---|
253 | ); |
---|
254 | |
---|
255 | $form['aggregator_category_selector'] = array( |
---|
256 | '#type' => 'radios', '#title' => t('Category selection type'), '#default_value' => variable_get('aggregator_category_selector', 'checkboxes'), |
---|
257 | '#options' => array('checkboxes' => t('checkboxes'), 'select' => t('multiple selector')), |
---|
258 | '#description' => t('The type of category selection widget displayed on categorization pages. (For a small number of categories, checkboxes are easier to use, while a multiple selector work well with large numbers of categories.)') |
---|
259 | ); |
---|
260 | |
---|
261 | return system_settings_form($form); |
---|
262 | } |
---|
263 | |
---|
264 | /** |
---|
265 | * Form builder; Generate a form to add/edit/delete aggregator categories. |
---|
266 | * |
---|
267 | * @ingroup forms |
---|
268 | * @see aggregator_form_category_validate() |
---|
269 | * @see aggregator_form_category_submit() |
---|
270 | */ |
---|
271 | function aggregator_form_category(&$form_state, $edit = array('title' => '', 'description' => '', 'cid' => NULL)) { |
---|
272 | $form['title'] = array('#type' => 'textfield', |
---|
273 | '#title' => t('Title'), |
---|
274 | '#default_value' => $edit['title'], |
---|
275 | '#maxlength' => 64, |
---|
276 | '#required' => TRUE, |
---|
277 | ); |
---|
278 | $form['description'] = array('#type' => 'textarea', |
---|
279 | '#title' => t('Description'), |
---|
280 | '#default_value' => $edit['description'], |
---|
281 | ); |
---|
282 | $form['submit'] = array('#type' => 'submit', '#value' => t('Save')); |
---|
283 | |
---|
284 | if ($edit['cid']) { |
---|
285 | $form['delete'] = array('#type' => 'submit', '#value' => t('Delete')); |
---|
286 | $form['cid'] = array('#type' => 'hidden', '#value' => $edit['cid']); |
---|
287 | } |
---|
288 | |
---|
289 | return $form; |
---|
290 | } |
---|
291 | |
---|
292 | /** |
---|
293 | * Validate aggregator_form_feed form submissions. |
---|
294 | */ |
---|
295 | function aggregator_form_category_validate($form, &$form_state) { |
---|
296 | if ($form_state['values']['op'] == t('Save')) { |
---|
297 | // Check for duplicate titles |
---|
298 | if (isset($form_state['values']['cid'])) { |
---|
299 | $category = db_fetch_object(db_query("SELECT cid FROM {aggregator_category} WHERE title = '%s' AND cid <> %d", $form_state['values']['title'], $form_state['values']['cid'])); |
---|
300 | } |
---|
301 | else { |
---|
302 | $category = db_fetch_object(db_query("SELECT cid FROM {aggregator_category} WHERE title = '%s'", $form_state['values']['title'])); |
---|
303 | } |
---|
304 | if ($category) { |
---|
305 | form_set_error('title', t('A category named %category already exists. Please enter a unique title.', array('%category' => $form_state['values']['title']))); |
---|
306 | } |
---|
307 | } |
---|
308 | } |
---|
309 | |
---|
310 | /** |
---|
311 | * Process aggregator_form_category form submissions. |
---|
312 | * |
---|
313 | * @todo Add delete confirmation dialog. |
---|
314 | */ |
---|
315 | function aggregator_form_category_submit($form, &$form_state) { |
---|
316 | if ($form_state['values']['op'] == t('Delete')) { |
---|
317 | $title = $form_state['values']['title']; |
---|
318 | // Unset the title: |
---|
319 | unset($form_state['values']['title']); |
---|
320 | } |
---|
321 | aggregator_save_category($form_state['values']); |
---|
322 | if (isset($form_state['values']['cid'])) { |
---|
323 | if (isset($form_state['values']['title'])) { |
---|
324 | drupal_set_message(t('The category %category has been updated.', array('%category' => $form_state['values']['title']))); |
---|
325 | if (arg(0) == 'admin') { |
---|
326 | $form_state['redirect'] = 'admin/content/aggregator/'; |
---|
327 | return; |
---|
328 | } |
---|
329 | else { |
---|
330 | $form_state['redirect'] = 'aggregator/categories/'. $form_state['values']['cid']; |
---|
331 | return; |
---|
332 | } |
---|
333 | } |
---|
334 | else { |
---|
335 | watchdog('aggregator', 'Category %category deleted.', array('%category' => $title)); |
---|
336 | drupal_set_message(t('The category %category has been deleted.', array('%category' => $title))); |
---|
337 | if (arg(0) == 'admin') { |
---|
338 | $form_state['redirect'] = 'admin/content/aggregator/'; |
---|
339 | return; |
---|
340 | } |
---|
341 | else { |
---|
342 | $form_state['redirect'] = 'aggregator/categories/'; |
---|
343 | return; |
---|
344 | } |
---|
345 | } |
---|
346 | } |
---|
347 | else { |
---|
348 | watchdog('aggregator', 'Category %category added.', array('%category' => $form_state['values']['title']), WATCHDOG_NOTICE, l(t('view'), 'admin/content/aggregator')); |
---|
349 | drupal_set_message(t('The category %category has been added.', array('%category' => $form_state['values']['title']))); |
---|
350 | } |
---|
351 | } |
---|