Merge lp://qastaging/~m-baert/ubuntu-drupal-planet/6.x into lp://qastaging/~swe3tdave-deactivatedaccount/ubuntu-drupal-planet/6.x

Proposed by David Giard
Status: Merged
Merged at revision: 17
Proposed branch: lp://qastaging/~m-baert/ubuntu-drupal-planet/6.x
Merge into: lp://qastaging/~swe3tdave-deactivatedaccount/ubuntu-drupal-planet/6.x
Diff against target: None lines
To merge this branch: bzr merge lp://qastaging/~m-baert/ubuntu-drupal-planet/6.x
Reviewer Review Type Date Requested Status
David Giard Approve
Review via email: mp+4715@code.qastaging.launchpad.net
To post a comment you must log in.
Revision history for this message
David Giard (swe3tdave-deactivatedaccount) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'planet.info'
2--- planet.info 2009-03-01 02:54:23 +0000
3+++ planet.info 2009-03-14 00:23:25 +0000
4@@ -1,6 +1,7 @@
5 ; $Id: planet.info,v 1.2 2007/05/30 03:22:01 daryl Exp $
6 name = Planet
7 description = Planet blog aggregator
8+; TODO better module definition, including specificity if possible.
9 package = Community - optional
10 version = 6.x
11 core = 6.x
12
13=== modified file 'planet.install'
14--- planet.install 2009-03-01 03:00:14 +0000
15+++ planet.install 2009-03-14 00:23:25 +0000
16@@ -10,37 +10,43 @@
17 'description' => t('The base table for planet.'),
18 'fields' => array(
19 'fid' => array(
20- 'description' => t('The primary identifier for a planet_feeds table.'),
21+ 'description' => t('Primary Key: Unique identifier for a planet RSS feed.'),
22 'type' => 'serial',
23 'unsigned' => TRUE,
24 'not null' => TRUE,
25 ),
26 'uid' => array(
27+ 'description' => t('Foreign key to {users}.uid . Identifies user who choose the feed.'),
28 'type' => 'int',
29 'unsigned' => 1,
30 'not null' => FALSE,
31 ),
32 'title' => array(
33 'type' => 'varchar',
34+ 'description' => t('Title of the feed.'),
35 'length' => 50,
36 'not null' => TRUE,
37 ),
38 'link' => array(
39 'type' => 'varchar',
40+ 'description' => t('URL to the feed'),
41 'length' => 80,
42 'not null' => TRUE,
43 ),
44 'image' => array(
45+ 'description' => t('An image representing the feed'),
46 'type' => 'varchar',
47 'length' => 120,
48 'not null' => FALSE,
49 ),
50 'checked' => array(
51+ 'description' => t('Last time feed was checked for new items, as Unix timestamp'),
52 'type' => 'int',
53 'not null' => FALSE,
54 ),
55 'frozen' => array(
56- 'type' => 'int',
57+ // TODO: add field description 'description' => t(''),
58+ 'type' => 'int', // TODO change to boolean when supported
59 'not null' => TRUE,
60 'default' => 0,
61 ),
62@@ -52,7 +58,7 @@
63 'description' => t('contain feed id and its corresponding nid'),
64 'fields' => array(
65 'id' => array(
66- 'description' => t('The primary identifier for a planet_items table'),
67+ 'description' => t('Primary key: Unique identifier for a planet feed item'),
68 'type' => 'serial',
69 'unsigned' => 1,
70 'not null' => TRUE,
71@@ -91,11 +97,9 @@
72 /**
73 * Implementation of hook_install()
74 *
75- * This will automatically install the database tables for the planet module for MySQL.
76- *
77- * If you are using another database, you will have to install the tables by hand, using the queries below as a reference.
78- *
79- *
80+ * This will automatically install the database tables for the planet
81+ * module, using Drupal's data abstraction layer.
82+ *
83 */
84
85 function planet_install() {
86@@ -106,9 +110,9 @@
87 /**
88 * Implementation of hook_uninstall()
89 *
90- * This will automatically uninstall the database tables for the planet module for MySQL.
91+ * Uninstalls planet module by removing its own database tables, nodes
92+ * and persistent variables.
93 *
94- *
95 */
96
97 function planet_uninstall() {
98
99=== modified file 'planet.module'
100--- planet.module 2009-03-08 19:00:05 +0000
101+++ planet.module 2009-03-20 16:05:00 +0000
102@@ -1,48 +1,92 @@
103 <?php
104 // $Id: planet.install Exp $
105
106-/**
107+ /**
108 * @file
109- * The planet module
110+ * The planet module.
111+ *
112+ * Planet is an aggregator that allows you to aggregate the blogs for
113+ * users in a given role (e.g. staff) and associate content with the
114+ * users rather than as a detached feed. This provides the benefit of
115+ * showing avatars with content, providing per-user aggregation of
116+ * planet content in addition to blog content, etc.
117 *
118 */
119
120+/**
121+ * Implementation of hook_node_info.
122+ *
123+ * @return An array of information on the module's node types.
124+ *
125+ * @ingroup planet_node
126+ */
127 function planet_node_info() {
128 return array(
129 'planet' => array(
130- 'name' => t('Planet Entry'),
131- 'module' => 'planet',
132- 'description' => t('Node to contain posts aggregated from various blogs.'),
133+ 'name' => t('Planet Entry'),
134+ 'module' => 'planet',
135+ 'description' => t('Node to contain posts aggregated from various blogs.'),
136 )
137 );
138 }
139
140 /**
141- * Implementation of hook_perm.
142+ * Implementation of hook_perm - Defines user permissions.
143+ * The suggested naming convention for permissions is "action_verb modulename".
144+ *
145+ * @return An array of permissions strings.
146+ *
147+ * @ingroup base
148 */
149 function planet_perm() {
150- return array('administer planet', 'administer own planet feeds');
151+ return array('administer planet', 'administer own planet feeds', 'view all planet nodes');
152 }
153
154+/**
155+ * Implementation of hook_help - Provides online user help.
156+ *
157+ * @param $path A Drupal menu router path the help is being requested for
158+ * @param $arg
159+ * @return A localized string containing the help text.
160+ *
161+ * @ingroup base
162+ */
163 function planet_help($path, $arg) {
164 switch ($path) {
165- case 'admin/help/planet':
166+ case 'admin/help#planet':
167+ // The module's help text, displayed on the admin/help page and through the module's individual help link.
168 $output = '<p>Planet is an aggregator that allows you to aggregate the blogs for users in a given role (e.g. staff) and associate content with the users rather than as a detached feed. This provides the benefit of showing avatars with content, providing per-user aggregation of planet content in addition to blog content, etc.</p>';
169 $output .= '<p>To use planet, go to admin/settings/planet and note the following sections:</p>';
170 $output .= '<ul>';
171 $output .= '<li><strong>General Settings</strong>. The role to select bloggers from lets you narrow the user list for when you\'re adding a feed and associating it with a user. A common setting will be to create a staff role and use this for planet.</li>';
172 $output .= '<li><strong>Feeds</strong>. This section lets you add a new feed. Give it a title, select an author, provide the feed url, and you\'re off. You\'ll have to manually refresh it or wait for a cron run for items to be imported.</li>';
173 $output .= '<li><strong>Feeds</strong>. This section lists current feeds, when they were last updated, how many items they have, and it allows you to edit, refresh, or freeze them. Freezing is a quick way to temporarily suspend updates from the given feed.</li>';
174+ // @DIFFGROUP output syntax
175+ $output .= '</ul>';
176 return $output;
177- case 'admin/modules#description':
178- return t('Aggregates RSS feeds and faciliates their association with site users who belong to a given role.');
179+ // @DIFFINFO in D6, admin/modules#description is moved to .info file
180 }
181 }
182
183-function planet_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) {
184+/**
185+ * Implementation of hook_view() - Displays a planet node.
186+ *
187+ * @param $node The node to be displayed.
188+ * @param $teaser Whether to generate only a summary ("teaser") of the node.
189+ * @param $page Whether the node is being displayed as a standalone page.
190+ * @return The modified $node parameter, properly presented for output.
191+ *
192+ * @ingroup planet_node
193+ * @CRUD{variables,R}
194+ * @CRUD{planet_items,R}
195+ */
196+function planet_view($node, $teaser = FALSE, $page = FALSE) {
197+ // @DIFFINFO removed $link param to match D6 hook definition
198 if ($page === true && variable_get('planet_redirect_page', 0) == 1) {
199- $obj = db_fetch_object(db_query('SELECT * FROM {planet_items} WHERE nid = %d', $node->nid));
200- if ($obj->nid == $node->nid && $obj->link != '') {
201+ // @DIFFINFO only 'link' field is used, so I restricted the query
202+ $obj = db_fetch_object(db_query('SELECT link FROM {planet_items} WHERE nid = %d', $node->nid));
203+ // @DIFFINFO if the query succeeds, $obj->nid == $node->nid , otherwise, $obj==FALSE,
204+ if ($obj && $obj->link != '') {
205 header('Location: '. $obj->link);
206 exit;
207 }
208@@ -52,22 +96,51 @@
209 }
210 }
211
212+/**
213+ * Implementation of hook_access() - Define access permissions for planet nodes (aka CRUD) .
214+ * @param $op The operation to be performed: 'create', 'view', 'update', 'delete'
215+ * @param $node The node on which the operation is to be performed, or, if it does not yet exist, the type of node to be created.
216+ * @param $account A user object representing the user for whom the operation is to be performed.
217+ * @return true if the user is allowed to perform operation, false otherwise.
218+ *
219+ * @ingroup planet_node
220+ */
221 function planet_access($op, $node, $account) {
222-
223-
224+ // @DIFFINFO using planet-dedicated permissions
225+ // Planet administrator has all permissions related to planet module
226+ if (user_access('administer planet', $account))
227+ return TRUE;
228+ // Users allowed to edit their own planet nodes, are also allowed to create them, others are not.
229+ $author = user_access('edit own planet feeds', $account);
230 if ($op == 'create') {
231- return user_access('edit own blog', $account) && $account->uid;
232+ return $author;
233 }
234
235+ // Does current user own requested node ?
236+ $own = $account->uid == $node->uid;
237+ if ($op == 'view')
238+ return $own || user_access('view all planet nodes');
239 if ($op == 'update' || $op == 'delete') {
240- if (user_access('edit own blog', $account) && ($account->uid == $node->uid) || user_access('administer nodes', $account)) {
241- return TRUE;
242- }
243+ return $author && $own; // ok if $author owns the node
244 }
245+ trigger_error("Unknown operation requested: $op");
246+ return FALSE;
247 }
248
249+/**
250+ * Implementation of hook_menu() - Defines menu items and page callbacks.
251+ *
252+ * @return An array of menu items.
253+ * Each menu item has a key corresponding to the Drupal path being registered.
254+ *
255+ * @ingroup base
256+ *
257+ * This diagram shows how requests are handled.
258+ * Each arrow is labeled with the permission required to access link.
259+ * The menu item colors reflect the item type.
260+ * @dotfile menu-links.dot "Menus and Pages"
261+ */
262 function planet_menu() {
263-
264 $items['admin/settings/planet'] = array(
265 'title' => 'Planet Settings',
266 'description' => 'Configure settings for the planet module.',
267@@ -84,31 +157,28 @@
268 );
269
270 // if (arg(0) == 'planet' && is_numeric(arg(1))) {
271+ // FIXME access denied http://localhost/drupal/?q=planet/1
272 $items['planet/'. '%'] = array(
273 'title' => 'planet',
274 'page callback' => 'planet_page_user',
275 'page arguments' => array(arg(1))
276 );
277-// }
278
279-// if (arg(3) == 'refresh' && is_numeric(arg(4))) {
280-
281+ // if (arg(3) == 'refresh' && is_numeric(arg(4))) {
282 $items['admin/settings/planet/refresh/%'] = array(
283 'title' => 'planet refresh',
284 'page callback' => 'planet_call_refresh',
285 'access arguments' => array('administer nodes'),
286 'type' => MENU_CALLBACK
287 );
288-// }
289
290-// if (is_numeric(arg(4)) && (arg(3) == 'freeze' || arg(3) == 'unfreeze')) {
291+ // if (is_numeric(arg(4)) && (arg(3) == 'freeze' || arg(3) == 'unfreeze')) {
292 $items['admin/settings/planet/'. arg(3) .'/%'] = array(
293 'title' => 'planet freeze',
294 'page callback' => 'planet_toggle_frozen',
295 'access arguments' => array('administer nodes'),
296 'type' => MENU_CALLBACK
297 );
298-// }
299
300 $items['planet'] = array(
301 'title' => 'Planet',
302@@ -128,6 +198,12 @@
303 return $items;
304 }
305
306+
307+/**
308+ * Page callback for 'admin/settings/planet/refresh/%' ("planet refresh")
309+ *
310+ * @ingroup page
311+ */
312 function planet_call_refresh() {
313 $title = planet_refresh();
314 watchdog('planet', 'Feed "'. $title .'" refreshed.');
315@@ -135,6 +211,12 @@
316 drupal_goto('admin/settings/planet');
317 }
318
319+/**
320+ * Page callback for 'admin/settings/planet/(un|)freeze/%' ("planet freeze")
321+ *
322+ * @ingroup page
323+ * @CRUD{planet_feeds,U}
324+ */
325 function planet_toggle_frozen() {
326
327 $fid = intval(arg(4));
328@@ -144,53 +226,57 @@
329 }
330
331
332+/**
333+ * Deletes a feed and related items
334+ * @param $fid the feed identifier key (integer)
335+ *
336+ * @internal
337+ * @ingroup planet_feed
338+ * @CRUD{planet_items,R}
339+ * @invoke{drupal_get_form,planet_multiple_delete_confirm}
340+ */
341+function planet__drop_feed($fid) {
342+ $result = db_query('SELECT nid FROM {planet_items} WHERE fid = %d', intval($edit['fid']));
343+ while ($node = db_fetch_object($result)) {
344+ $nodes[$node->nid] = TRUE;
345+ }
346+ return drupal_get_form('planet_multiple_delete_confirm', $nodes,
347+ intval($edit['fid']), 'user/'. $user->uid .'/planet');
348+}
349+
350+/**
351+ * Page callback for 'user/%user/planet' ("Planet Feeds")
352+ *
353+ * @ingroup page
354+ * @CRUD{planet_feeds,R}
355+ * @invoke{drupal_get_form,planet_multiple_delete_confirm_submit}
356+ * @invoke{drupal_get_form,planet_feed_form}
357+ */
358 function planet_user_feeds() {
359-global $user;
360-if ($_POST) {
361+ global $user;
362+ if ($_POST) {
363 $edit = $_POST;
364- if ($_POST['op'] == 'Delete' && intval($edit['fid']) > 0) {
365- $result = db_query('SELECT nid FROM {planet_items} WHERE fid = %d', intval($edit['fid']));
366- while ($node = db_fetch_object($result)) {
367- $nodes[$node->nid] = TRUE;
368- }
369- return drupal_get_form('planet_multiple_delete_confirm', $nodes, intval($edit['fid']), 'user/'. $user->uid .'/planet');
370- }
371- else if ($_POST['op'] == 'Delete all' && $_POST['confirm'] == 1) {
372- $edit['fid'] = intval(arg(3));
373+ $fid = intval($edit['fid']);
374+ if (($_POST['op'] == 'Delete') && ($fid != 0)) {
375+ return planet__drop_feed($fid);
376+ } else if ($_POST['op'] == 'Delete all' && $_POST['confirm'] == 1) {
377+ $edit['fid'] = intval(arg(3)); // @deprecated arg()
378 $edit['redirect'] = 'user/'. $user->uid .'/planet';
379 return drupal_get_form('planet_multiple_delete_confirm_submit', $edit);
380- }
381- else {
382- if (isset($edit['fid']) && intval($edit['fid']) == 0) {
383- db_query('INSERT INTO {planet_feeds} (uid, title, link, image, checked, frozen) VALUES(%d, "%s", "%s", "%s", 0, 0)', $user->uid, $edit['title'], $edit['link'], $edit['image']);
384- $edit_r = db_fetch_array(db_query('SELECT fid FROM {planet_feeds} WHERE uid = %d AND title = "%s" AND link = "%s"', $user->uid, $edit['title'], $edit['link']));
385- $title = planet_refresh(intval($edit_r['fid']));
386- drupal_set_message('Added new feed: ' . $title);
387- }
388- else if ($edit['fid'] && intval($edit['fid']) > 0) {
389- db_query('UPDATE {planet_feeds} SET uid = %d, title="%s", link = "%s", image="%s" WHERE fid=%d', $user->uid, $edit['title'], $edit['link'], $edit['image'], $edit['fid']);
390- drupal_set_message('Edited "'. $edit['title'] .'" feed.');
391- }
392- else {
393- if ($edit['planet_author_roles']) {
394- variable_set('planet_author_roles', $edit['planet_author_roles']);
395- }
396- if ($edit['planet_filter_formats']) {
397- variable_set('planet_filter_formats', $edit['planet_filter_formats']);
398- }
399- if ($edit['planet_redirect_page'] == 1) {
400- variable_set('planet_redirect_page', $edit['planet_redirect_page']);
401- }
402- else {
403- variable_del('planet_redirect_page');
404- }
405- drupal_set_message('Edited general planet settings.');
406+ } else {
407+ if (isset($edit['fid'])) {
408+ if (intval($edit['fid']) == 0) {
409+ planet__add_feed($edit);
410+ } else {
411+ planet__update_feed($edit);
412+ }
413+ } else {
414+ planet__update_vars($edit);
415 }
416 }
417 drupal_goto('user/'. $user->uid .'/planet');
418- }
419- else {
420- $fid = intval(arg(3));
421+ } else { // no $_POST
422+ $fid = intval(arg(3)); // @deprecated: arg()
423 if ($fid > 0) {
424 $edit = db_fetch_array(db_query('SELECT * FROM {planet_feeds} WHERE fid = %d', $fid));
425 $output .= drupal_get_form('planet_feed_form', $edit, true, $user);
426@@ -199,32 +285,143 @@
427
428 $output .= drupal_get_form('planet_feed_form', $edit, false, $user);
429
430- // $result = db_query('SELECT *, (UNIX_TIMESTAMP(NOW()) - checked) _checked FROM {planet_feeds}');
431- $result = db_query('SELECT COUNT(f.fid) cnt, f.*, (UNIX_TIMESTAMP(NOW()) - checked) _checked FROM {planet_feeds} f LEFT OUTER JOIN {planet_items} i ON i.fid = f.fid WHERE f.uid = %d GROUP BY f.fid;', $user->uid);
432+ $output .= '<h2>Feeds</h2>';
433+ $output .= planet__build_user_feeds_table();
434+ }
435+ print theme('page', $output);
436+ }
437+}
438+
439+// Note: I use 'planet__' prefix to name internal functions
440+// TODO: apply the same naming convention (this one or another) in whole module
441+/**
442+ * @todo merge with planet__build_admin_feeds_table()
443+ *
444+ * @ingroup planet_feed
445+ * @internal
446+ * @CRUD{planet_feeds,R}
447+ * @CRUD{planet_items,R}
448+ */
449+function planet__build_user_feeds_table() {
450+ // @DIFFINFO renamed planet__build_feeds_table1
451+ global $user;
452+ $feeds = db_query('SELECT fid, title, checked FROM {planet_feeds} '
453+ . ' WHERE uid = %d;', $user->uid);
454 $rows = array();
455 $headers = array('Feed', 'Items', 'Edit', 'Last checked');
456- while ($feed = db_fetch_object($result)) {
457- $checked = intval($feed->_checked / 60) .' minutes';
458- if ($feed->_checked % 60 > 0) {
459+ $now = time();
460+ $items_statement = 'SELECT count(*) FROM {planet_items}'
461+ . ' WHERE fid=%d';
462+ // TODO: change this to prepared statement when supported by drupal DB abstraction layer.
463+ while ($feed = db_fetch_object($feeds)) {
464+ $_checked = $now - $feed->checked;
465+ $checked = intval($_checked / 60) .' minutes';
466+ if ($_checked % 60 > 0) {
467 $checked .= ', '. $feed->_checked % 60 .' seconds';
468 }
469 $checked .= ' ago';
470+ $items = db_query($items_statement, $feed->fid);
471+ if (!$items) trigger_error('ERROR while counting feed items.');
472+ $cnt = db_result($items);
473 array_push($rows, array(
474 $feed->title,
475- $feed->cnt,
476+ $cnt,
477 l('edit', 'user/'. $user->uid .'/planet/'. intval($feed->fid)),
478 $checked,
479 )
480 );
481 }
482- $output .= '<h2>Feeds</h2>';
483- $output .= theme('table', $headers, $rows);
484- }
485- print theme('page', $output);
486- }
487-}
488-
489-
490+ return theme('table', $headers, $rows);
491+}
492+
493+/**
494+ * Adds a new feed to planet_feeds table.
495+ * @param $data associative array with keys
496+ * 'uid' (optional), 'title', 'link', 'image' (optional)
497+ * @return success status
498+ *
499+ * @ingroup planet_feed
500+ * @internal
501+ * @CRUD{planet_feeds,C}
502+ */
503+function planet__add_feed($data) {
504+ $data['checked'] = 0;
505+ $data['frozen'] = 0;
506+ if (isset($data['fid'])) { // @DEBUGGING
507+ trigger_error('Primary key fid shouldn\'t be set for a need feed (value: {$data->fid}). Record not added.', E_ERROR);
508+ return FALSE;
509+ }
510+ $rslt = drupal_write_record('planet_feeds', $data);
511+ if ($rslt==SAVED_NEW) {
512+ $title = planet_refresh(intval($data['fid']));
513+ drupal_set_message('Added new feed: ' . $title);
514+ return TRUE;
515+ }
516+ trigger_error('Failed to add new feed');
517+ return FALSE;
518+}
519+
520+/**
521+ * Updates an existing feed in planet_feeds table.
522+ * @param $data associative array with keys
523+ * 'fid' (mandatory, primary key),
524+ * other fields as needed:
525+ * 'uid', 'title', 'link', 'image', 'checked', 'frozen'
526+ * @return success status
527+ *
528+ * @ingroup planet_feed
529+ * @internal
530+ * @CRUD{planet_feeds,U}
531+*/
532+function planet__update_feed($data) {
533+ $rslt = drupal_write_record('planet_feeds', $data, 'fid');
534+ if ($rslt==SAVED_UPDATED) {
535+ drupal_set_message('Edited "'. $data['title'] .'" feed.');
536+ return TRUE;
537+ }
538+ if ($rslt==SAVED_NEW) // @DEBUGGING
539+ trigger_error('Feed {$data->fid} didn\'t exist. Record added.', E_ERROR);
540+ else
541+ trigger_error('Failed to edit feed');
542+ return FALSE;
543+}
544+
545+/**
546+ * Updates an planet settings persistent variables.
547+ * @param $data associative array with all optional keys
548+ * 'planet_author_roles', 'planet_filter_formats',
549+ * 'planet_redirect_page'.
550+ *
551+ * @ingroup isettings
552+ * @internal
553+ * @CRUD{variables,CUD}
554+*/
555+function planet__update_vars($data) {
556+ if ($edit['planet_author_roles']) {
557+ variable_set('planet_author_roles', $edit['planet_author_roles']);
558+ }
559+ if ($edit['planet_filter_formats']) {
560+ variable_set('planet_filter_formats', $edit['planet_filter_formats']);
561+ }
562+ if ($edit['planet_redirect_page'] == 1) {
563+ variable_set('planet_redirect_page', $edit['planet_redirect_page']);
564+ } else {
565+ variable_del('planet_redirect_page');
566+ }
567+ drupal_set_message('Edited general planet settings.');
568+}
569+
570+/**
571+ * Page callback for 'admin/settings/planet' ("Planet Settings")
572+ *
573+ * @ingroup page
574+ * @CRUD{planet_items,R}
575+ * @CRUD{planet_feeds,R}
576+ * @invoke{drupal_get_form,planet_multiple_delete_confirm}
577+ * @invoke{drupal_get_form,planet_multiple_delete_confirm_submit}
578+ * @invoke{drupal_get_form,planet_feed_form}
579+ * @invoke{drupal_get_form,planet_settings_form}
580+ */
581 function _planet_settings() {
582 if ($_POST) {
583 $edit = $_POST;
584@@ -241,37 +438,23 @@
585 $edit['redirect'] = 'admin/settings/planet';
586 return drupal_get_form('planet_multiple_delete_confirm_submit', $edit);
587 }
588- else {
589- if (isset($edit['fid']) && intval($edit['fid']) == 0) {
590- db_query('INSERT INTO {planet_feeds} (uid, title, link, image, checked, frozen) VALUES(%d, "%s", "%s", "%s", 0, 0)', $edit['uid'], $edit['title'], $edit['link'], $edit['image']);
591- $edit_r = db_fetch_array(db_query('SELECT fid FROM {planet_feeds} WHERE uid = %d AND title = "%s" AND link = "%s"', $edit['uid'], $edit['title'], $edit['link']));
592- $title = planet_refresh(intval($edit_r['fid']));
593- drupal_set_message('Added new feed: ' . $title);
594- }
595- else if ($edit['fid'] && intval($edit['fid']) > 0) {
596- db_query('UPDATE {planet_feeds} SET uid = %d, title="%s", link = "%s", image="%s" WHERE fid=%d', $edit['uid'], $edit['title'], $edit['link'], $edit['image'], $edit['fid']);
597- drupal_set_message('Edited "'. $edit['title'] .'" feed.');
598- }
599- else {
600- if ($edit['planet_author_roles']) {
601- variable_set('planet_author_roles', $edit['planet_author_roles']);
602- }
603- if ($edit['planet_filter_formats']) {
604- variable_set('planet_filter_formats', $edit['planet_filter_formats']);
605- }
606- if ($edit['planet_redirect_page'] == 1) {
607- variable_set('planet_redirect_page', $edit['planet_redirect_page']);
608- }
609- else {
610- variable_del('planet_redirect_page');
611- }
612- drupal_set_message('Edited general planet settings.');
613+ else {
614+ if (isset($edit['fid'])) {
615+ if (intval($edit['fid']) == 0) {
616+ planet__add_feed($edit);
617+ } else {
618+ planet__update_feed($edit);
619+ }
620+ } else {
621+ // TODO if user needs to click separately for each fieldset,
622+ // why not using different forms ?
623+ // or conversely, allow setting everything at once ?
624+ planet__update_vars($edit);
625 }
626 }
627 drupal_goto('admin/settings/planet');
628- }
629- else {
630- $fid = intval(arg(3));
631+ } else {
632+ $fid = intval(arg(3)); // @deprecated arg()
633 if ($fid > 0) {
634 $edit = db_fetch_array(db_query('SELECT * FROM {planet_feeds} WHERE fid = %d', $fid));
635 $output .= drupal_get_form('planet_feed_form', $edit, true);
636@@ -279,38 +462,72 @@
637 else {
638
639 $output .= drupal_get_form('planet_settings_form');
640- //$output .= drupal_get_form('settings', $form);
641- //$output .= $form;
642
643 $output .= drupal_get_form('planet_feed_form', $edit);
644
645- // $result = db_query('SELECT *, (UNIX_TIMESTAMP(NOW()) - checked) _checked FROM {planet_feeds}');
646- $result = db_query('SELECT COUNT(f.fid) cnt, f.*, (UNIX_TIMESTAMP(NOW()) - checked) _checked FROM {planet_feeds} f LEFT OUTER JOIN {planet_items} i ON i.fid = f.fid GROUP BY f.fid;');
647- $rows = array();
648- $headers = array('Feed', 'Items', 'Edit', 'Last checked', 'Refresh', 'Freeze');
649- while ($feed = db_fetch_object($result)) {
650- $checked = intval($feed->_checked / 60) .' minutes';
651- if ($feed->_checked % 60 > 0) {
652- $checked .= ', '. $feed->_checked % 60 .' seconds';
653- }
654- $checked .= ' ago';
655- array_push($rows, array(
656- $feed->title,
657- $feed->cnt,
658- l('edit', 'admin/settings/planet/'. intval($feed->fid)),
659- $checked,
660- l('refresh', 'admin/settings/planet/refresh/'. intval($feed->fid)),
661- l($feed->frozen ? 'unfreeze' : 'freeze', 'admin/settings/planet/'. ($feed->frozen ? 'unfreeze/' : 'freeze/') . intval($feed->fid))
662- )
663- );
664- }
665 $output .= '<h2>Feeds</h2>';
666- $output .= theme('table', $headers, $rows);
667+ $output .= planet__build_admin_feeds_table();
668 }
669 print theme('page', $output);
670 }
671 }
672
673+/**
674+ * builds an HTML table of feeds for administrator interaction.
675+ *
676+ * @return
677+ *
678+ * @ingroup planet_feed
679+ * @internal
680+ * @CRUD{planet_feeds,R}
681+ * @CRUD{planet_items,R}
682+ */
683+function planet__build_admin_feeds_table() {
684+ // @DIFFINFO renamed planet__build_feeds_table() {
685+ global $user;
686+ $feeds = db_query('SELECT fid, title, checked, frozen FROM {planet_feeds} '
687+ . ' WHERE uid = %d;', $user->uid);
688+ $rows = array();
689+ $headers = array('Feed', 'Items', 'Edit', 'Last checked', 'Refresh', 'Freeze');
690+ $now = time();
691+ $items_statement = 'SELECT count(*) FROM {planet_items} WHERE fid=%';
692+ // TODO: change this to prepared statement when supported by drupal DB Abstraction Layer.
693+ while ($feed = db_fetch_object($feeds)) {
694+ $_checked = $now - $feed->checked;
695+ $checked = intval($_checked / 60) .' minutes';
696+ if ($_checked % 60 > 0) {
697+ $checked .= ', '. $feed->_checked % 60 .' seconds';
698+ }
699+ $checked .= ' ago';
700+ $items = db_query($items_statement, $feed->fid);
701+ if (!$items) trigger_error('ERROR while counting feed items.');
702+ $cnt = db_result($items);
703+ $fid = strval($feed->fid);
704+ array_push($rows, array(
705+ $feed->title,
706+ $cnt,
707+ l('edit', 'admin/settings/planet/'. $fid),
708+ $checked,
709+ l('refresh', 'admin/settings/planet/refresh/'. $fid),
710+ l($feed->frozen ? 'unfreeze' : 'freeze', 'admin/settings/planet/'. ($feed->frozen ? 'unfreeze/' : 'freeze/') . $fid)
711+ )
712+ );
713+ }
714+ return theme('table', $headers, $rows);
715+}
716+
717+/**
718+ * TODO.
719+ *
720+ * @param &$form_state
721+ * @param $nodes
722+ * @param $fid
723+ * @param $redirect
724+ * @return
725+ *
726+ * @ingroup iforms
727+ * @CRUD{node,R}
728+ */
729 function planet_multiple_delete_confirm(&$form_state, $nodes, $fid, $redirect) {
730 $form_state['values']['fid'] = $fid;
731 $form_state['values']['redirect'] = $redirect;
732@@ -333,21 +550,42 @@
733 t('Delete all'), t('Cancel'));
734 }
735
736+/**
737+ * TODO.
738+ *
739+ * @param &$form_state
740+ * @param $edit
741+ * @return
742+ *
743+ * @ingroup iforms
744+ * @CRUD{node,D}
745+ * @CRUD{planet_items,D}
746+ * @CRUD{planet_feeds,D}
747+ */
748 function planet_multiple_delete_confirm_submit(&$form_state, $edit) {
749 $fid = $edit['fid'];
750 if ($edit['confirm']) {
751 foreach ($edit['nodes'] as $nid => $value) {
752 node_delete($nid);
753 }
754+ // @DIFFINFO inverted drop order to respect foreign keys
755+ db_query('DELETE FROM {planet_items} WHERE fid = %d', $fid);
756 db_query('DELETE FROM {planet_feeds} WHERE fid = %d', $fid);
757- db_query('DELETE FROM {planet_items} WHERE fid = %d', $fid);
758 drupal_set_message(t('The feed and items have been deleted.'));
759 }
760 drupal_goto($edit['redirect']);
761 }
762
763
764-
765+/**
766+ * TODO.
767+ *
768+ * @param &$form_state
769+ * @return
770+ * @ingroup iforms
771+ * @CRUD{role,R}
772+ * @CRUD{variables,R}
773+ */
774 function planet_settings_form(&$form_state) {
775 $roles = array();
776
777@@ -402,6 +640,20 @@
778 }
779
780
781+/**
782+ * TODO.
783+ *
784+ * @param &$form_state
785+ * @param $edit
786+ * @param $individual
787+ * @param $user
788+ * @return
789+ * @ingroup iforms
790+ * @CRUD{users,R}
791+ * @CRUD{role,R}
792+ * @CRUD{users_roles,R}
793+ * @CRUD{variables,R}
794+ */
795 function planet_feed_form(&$form_state, $edit = array(), $individual = false, $user = NULL) {
796 $uids = array();
797 $result = db_query('SELECT u.uid, u.name FROM {users} u, {role} r, {users_roles} ur WHERE u.uid = ur.uid AND ur.rid = r.rid AND r.rid = %d ORDER BY u.name ASC', variable_get('planet_author_roles', 2));
798@@ -474,6 +726,13 @@
799 return $form;
800 }
801
802+/**
803+ * Implementation of hook_cron - Perform periodic actions.
804+ *
805+ * @return none
806+ * @ingroup system
807+ * @CRUD{planet_feeds,R}
808+ */
809 function planet_cron() {
810 $result = db_query('SELECT fid FROM {planet_feeds} WHERE frozen = 0');
811 while ($feed = db_fetch_object($result)) {
812@@ -482,6 +741,17 @@
813 }
814 }
815
816+
817+/**
818+ * Private function; Checks a news feed for new items.
819+ *
820+ * @param $fid feed identifier (defaults to arg(4))
821+ * @return
822+ *
823+ * @private
824+ * @CRUD{planet_feeds,U}
825+ * @invoke{module_invoke,taxonomy_node_get_terms}
826+ */
827 function planet_refresh($fid = null) {
828 if (!$fid) {
829 $fid = intval(arg(4));
830@@ -638,60 +908,8 @@
831 /**
832 * Private function; Parse HTTP headers from data retreived with cURL
833 * from: http://pl2.php.net/manual/en/function.curl-setopt.php#42009
834- */
835-function planet_parse_response($response) {
836- /*
837- ***original code extracted from examples at
838- ***http://www.webreference.com/programming
839- /php/cookbook/chap11/1/3.html
840-
841- ***returns an array in the following format which varies depending on headers returned
842-
843- [0] => the HTTP error or response code such as 404
844- [1] => Array
845- (
846- [Server] => Microsoft-IIS/5.0
847- [Date] => Wed, 28 Apr 2004 23:29:20 GMT
848- [X-Powered-By] => ASP.NET
849- [Connection] => close
850- [Set-Cookie] => COOKIESTUFF
851- [Expires] => Thu, 01 Dec 1994 16:00:00 GMT
852- [Content-Type] => text/html
853- [Content-Length] => 4040
854- )
855- [2] => Response body (string)
856- */
857-
858- do {
859- list($response_headers, $response) = explode("\r\n\r\n", $response, 2);
860- $response_header_lines = explode("\r\n", $response_headers);
861-
862- // first line of headers is the HTTP response code
863- $http_response_line = array_shift($response_header_lines);
864- if (preg_match('@^HTTP/[0-9]\.[0-9] ([0-9]{3})@', $http_response_line, $matches)) {
865- $response_code = $matches[1];
866- }
867- else {
868- $response_code = "Error";
869- }
870- }
871- while (substr($response_code, 0, 1) == "1");
872-
873- $response_body = $response;
874-
875- // put the rest of the headers in an array
876- $response_header_array = array();
877- foreach ($response_header_lines as $header_line) {
878- list($header, $value) = explode(':', $header_line, 2);
879- $response_header_array[$header] = trim($value);
880- }
881-
882- return array($response_code, $response_header_array, $response_body, $http_response_line);
883-}
884-
885-/**
886- * Private function; Gets data from given URL :)
887- */
888+ * @ingroup rss
889+ * @private
890 function planet_http_request($url, $headers = array(), $timeout = 15, $method = 'GET', $data = NULL, $follow = 3) {
891 if (!function_exists('curl_init')) {
892 return drupal_http_request($url, $headers, $method, $data, $follow);
893@@ -750,11 +968,6 @@
894 }
895
896 /**
897- * Private function; Checks a news feed for new items.
898- */
899-
900-
901-/**
902 * Private function;
903 * Parse the W3C date/time format, a subset of ISO 8601. PHP date parsing
904 * functions do not handle this format.
905@@ -763,6 +976,8 @@
906 *
907 * @param $date_str A string with a potentially W3C DTF date.
908 * @return A timestamp if parsed successfully or -1 if not.
909+ * @ingroup rss
910+ * @private
911 */
912 function planet_parse_w3cdtf($date_str) {
913 if (preg_match('/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/', $date_str, $match)) {
914@@ -799,6 +1014,8 @@
915 *
916 * @param $ord Number
917 * @return UTF-8 string
918+ * @ingroup rss
919+ * @private
920 */
921 function planet_replace_num_entity($ord) {
922 $ord = $ord[1];
923@@ -959,6 +1176,8 @@
924 /**
925 * Private function; Convert named entities to UTF-8 characters
926 * from: http://pl2.php.net/manual/en/function.html-entity-decode.php#51722
927+ * @ingroup rss
928+ * @private
929 */
930 function planet_replace_name_entities(&$text) {
931 static $ttr;
932@@ -974,23 +1193,20 @@
933
934 /**
935 * Private function; Convert all entities to UTF-8 characters
936+ * @ingroup rss
937+ * @private
938+ * @invoke{preg_replace_callback,planet_replace_num_entity}
939 */
940 function planet_replace_entities(&$text) {
941 $result = planet_replace_name_entities($text);
942 return preg_replace_callback('/&#([0-9a-fx]+);/mi', 'planet_replace_num_entity', $result);
943 }
944
945-/**
946- * Private function; Clone object function to stay compatible with both php4 and php5
947- * from: Drupal 4.7CVS
948- * TODO: remove after moving to Drupal 4.7
949- */
950-function planet_clone($object) {
951- return version_compare(phpversion(), '5.0') < 0 ? $object : clone($object);
952-}
953
954 /**
955 * Private function; Convert relative URLs
956+ * @ingroup rss
957+ * @private
958 */
959 function planet_convert_relative_urls(&$data, $base_url) {
960 $src = '%( href| src)="(?!\w+://)/?([^"]*)"%';
961@@ -1000,6 +1216,13 @@
962
963 /**
964 * Private function; Creates nodes from data found in given xml_tree
965+ *
966+ * @ingroup rss
967+ * @private
968+ * @CRUD{variables,R}
969+ * @CRUD{planet_items,R}
970+ * @CRUD{node,CU}
971+ * @invoke{module_invoke,taxonomy_node_get_terms}
972 */
973 function planet_parse_items(&$xml_tree, &$feed) {
974
975@@ -1229,10 +1452,16 @@
976 }
977 //print '<pre>'. print_r($entry, 1) .'</pre>';
978 node_save($entry);
979- db_query('INSERT INTO {planet_items} (fid, nid, guid, link, created) VALUES(%d, %d, "%s", "%s", UNIX_TIMESTAMP(NOW()))', $feed->fid, $entry->nid, $guid, $link);
980+ $item_record = array('fid' => $feed->fid,
981+ 'nid' => $entry->nid,
982+ 'guid'=> $guid,
983+ 'link' =>$link,
984+ 'created' => time());
985+ drupal_write_record('planet_items', $item_record);
986 watchdog('planet', 'Adding '. $title);
987 drupal_set_message('Adding '. $title);
988 }
989+ // TODO split this huge function
990 }
991
992 return $items_added;
993@@ -1241,6 +1470,12 @@
994
995 /**
996 * Private function; parses given XML data and returns array
997+ *
998+ * @ingroup rss
999+ * @private
1000+ * @invoke{xml_set_element_handler,planet_element_start}
1001+ * @invoke{xml_set_element_handler,planet_element_end}
1002+ * @invoke{xml_set_character_data_handler,planet_element_data}
1003 */
1004 function planet_parse_xml(&$data) {
1005 global $xml_tree, $xml_paths, $xml_path_cur;
1006@@ -1297,6 +1532,8 @@
1007
1008 /**
1009 * Private call-back function used by the XML parser.
1010+ * @ingroup rss
1011+ * @internal
1012 */
1013 function planet_element_start($parser, $name, $attributes) {
1014 global $xml_tree, $xml_paths, $xml_path_cur;
1015@@ -1308,6 +1545,8 @@
1016
1017 /**
1018 * Private call-back function used by the XML parser.
1019+ * @ingroup rss
1020+ * @private
1021 */
1022 function planet_element_end($parser, $name) {
1023 global $xml_tree, $xml_paths, $xml_path_cur;
1024@@ -1322,6 +1561,8 @@
1025
1026 /**
1027 * Private call-back function used by the XML parser.
1028+ * @ingroup rss
1029+ * @private
1030 */
1031 function planet_element_data($parser, $data) {
1032 global $xml_tree, $xml_paths, $xml_path_cur;
1033@@ -1333,6 +1574,12 @@
1034 }
1035 }
1036
1037+/**
1038+ * Page callback for 'planet' ("Planet").
1039+ * @ingroup page
1040+ * @CRUD{node,R}
1041+ * @CRUD{variables,R}
1042+ */
1043 function planet_page_last() {
1044 global $user;
1045
1046@@ -1351,6 +1598,12 @@
1047 print theme('page', $output);
1048 }
1049
1050+/**
1051+ * Page callback for 'planet/feed' ("Planet").
1052+ * @ingroup page
1053+ * @CRUD{node,R}
1054+ * @CRUD{menu_links,R}
1055+ */
1056 function planet_feed() {
1057 $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'planet' AND n.status = 1 ORDER BY n.created DESC"), 0, 15);
1058 $title = db_fetch_array(db_query("SELECT link_title FROM {menu_links} WHERE link_path = 'planet'"));
1059@@ -1363,12 +1616,14 @@
1060 while ($row = db_fetch_object($result)) {
1061 $items[] = $row->nid;
1062 }
1063-
1064+ // generate RSS feed from $items set of nodes.
1065 node_feed($items, $channel);
1066 }
1067
1068 /**
1069- * Implementation of hook_user().
1070+ * Implementation of hook_user() - React when operations are performed on user accounts.
1071+ * @ingroup system
1072+ * @CRUD{planet_feeds,R}
1073 */
1074 function planet_user($type, &$edit, &$user) {
1075 if ($type == 'view' && user_access('edit own blog', $user)) {
1076@@ -1390,6 +1645,8 @@
1077
1078 /**
1079 * Menu callback; displays a Drupal page containing recent planet entries.
1080+ * @todo remove orphan function, or reuse it
1081+ * @ingroup page
1082 */
1083 function planet_page($a = NULL, $b = NULL) {
1084
1085@@ -1409,6 +1666,13 @@
1086 }
1087 }
1088
1089+/**
1090+ * Page callback for 'planet/%' ("planet").
1091+ * @ingroup page
1092+ *
1093+ * @CRUD{node,R}
1094+ * @CRUD{variables,R}
1095+ */
1096 function planet_page_user($uid) {
1097 global $user;
1098
1099@@ -1441,12 +1705,28 @@
1100 }
1101 }
1102
1103+/**
1104+ * Implementation of hook_load - Load node-type-specific information.
1105+ *
1106+ * @param $node The node being loaded.
1107+ * @return An object containing properties of the node being loaded.
1108+ * @ingroup system
1109+ * @CRUD{planet_items,R}
1110+ */
1111 function planet_load($node) {
1112 $additions = db_fetch_object(db_query('SELECT link, guid FROM {planet_items} WHERE nid = %d', $node->nid));
1113 return $additions;
1114 }
1115
1116-function planet_form(&$node, &$param) {
1117+/**
1118+ * Implementation of hook_form - Display a node editing form.
1119+ *
1120+ * @param &$node The node being added or edited.
1121+ * @param $form_state The form state array (unused).
1122+ * @return An array containing the form elements to be displayed in the node edit form.
1123+ * @ingroup planet_node
1124+ */
1125+function planet_form(&$node, &$form_state) {
1126 $form = array();
1127 $form['title'] = array('#type' => 'textfield', '#title' => 'Title', '#value' => $node->title, '#size' => 30, '#maxlength' => 80);
1128 $form['body'] = array('#type' => 'textarea', '#title' => 'Body', '#value' => $node->body);

Subscribers

People subscribed via source and target branches

to all changes: