/[drupal]/contributions/modules/nodeprofile/content_profile.module
ViewVC logotype

Contents of /contributions/modules/nodeprofile/content_profile.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download) (as text)
Fri Jan 25 10:57:36 2008 UTC (22 months ago) by fago
Branch: MAIN
CVS Tags: HEAD
File MIME type: text/x-php
checked in a first prototype of content profile
1 <?php
2 // $Id: content_profile.module,v 1.0 2008/01/13 21:47:00 littleant Exp $
3
4 /**
5 * @file
6 * Marks content types as profiles
7 */
8
9 /**
10 * Implementation of hook_menu().
11 */
12 function content_profile_menu() {
13 $items = array();
14
15 //Register a path for each content profile type
16 foreach (content_profile_get_types('names') as $type => $typename) {
17 $items['admin/content/types/'. str_replace('_', '-', $type) .'/edit'] = array(
18 'title' => 'Edit',
19 'type' => MENU_DEFAULT_LOCAL_TASK,
20 );
21 $items['admin/content/types/'. str_replace('_', '-', $type) .'/profile'] = array(
22 'title' => 'Content profile',
23 'description' => 'Configure the display and management of this content profile.',
24 'page callback' => 'drupal_get_form',
25 'page arguments' => array('content_profile_admin_settings', $type),
26 'access callback' => 'user_access',
27 'access arguments' => array('administer nodes'),
28 'type' => MENU_LOCAL_TASK,
29 'weight' => 1,
30 );
31 }
32 return $items;
33 }
34
35 /**
36 * Implementation of hook_node_info()
37 */
38 function content_profile_node_info() {
39 return array('profile' => array(
40 'name' => t('Profile'),
41 'has_title' => TRUE,
42 'has_body' => TRUE,
43 'custom' => TRUE,
44 'modified' => TRUE,
45 'locked' => FALSE,
46 ));
47 }
48
49 /**
50 * Menu callback; content profile settings.
51 */
52 function content_profile_admin_settings(&$form_state, $type) {
53 $form_state['type'] = $type;
54
55 $form['weight'] = array(
56 '#type' => 'weight',
57 '#title' => t("Weight"),
58 '#default_value' => content_profile_get_settings($type, 'weight'),
59 '#description' => t('The weight of content of this content type where ever they appear - this applies to the input form integration as well to the display integration.'),
60 '#weight' => 5,
61 );
62 $form['display'] = array(
63 '#type' => 'fieldset',
64 '#title' => t('Display settings'),
65 '#description' => t('Customize the display of this content profile.'),
66 '#collapsible' => TRUE,
67 );
68 $form['display']['user_display'] = array(
69 '#type' => 'radios',
70 '#title' => t("User page display style"),
71 '#default_value' => content_profile_get_settings($type, 'user_display'),
72 '#options' => array(
73 0 => t('Don\'t display this content profile on the user account page'),
74 'link' => t('Display it as link to the profile content'),
75 'full' => t('Display the full content'),
76 'teaser' => t('Display the content\'s teaser'),
77 ),
78 );
79 $form['display']['edit_link'] = array(
80 '#type' => 'checkbox',
81 '#title' => t("Include an edit link to the display"),
82 '#default_value' => content_profile_get_settings($type, 'edit_link'),
83 );
84 $form['display']['add_link'] = array(
85 '#type' => 'checkbox',
86 '#title' => t("Show a link to the content profile creation page, if there is no profile."),
87 '#default_value' => content_profile_get_settings($type, 'add_link'),
88 '#description' => t("If selected and the user has no profile of this type yet, a link to add one is shown on the user page."),
89 );
90 $form['submit'] = array(
91 '#type' => 'submit',
92 '#value' => t('Submit'),
93 '#weight' => 10,
94 );
95 return $form;
96 }
97
98 function content_profile_admin_settings_submit($form, &$form_state) {
99 $settings = content_profile_get_settings($form_state['type']);
100 foreach (content_profile_settings_info() as $setting => $default) {
101 $settings[$setting] = $form_state['values'][$setting];
102 }
103 content_profile_set_settings($form_state['type'], $settings);
104 drupal_set_message('Your changes have been saved.');
105 }
106
107 /**
108 * Determine if a given node is a content_profile.
109 * @param $type The node object or the node's type
110 */
111 function is_content_profile($type) {
112 if (is_object($type)) {
113 $type = $type->type;
114 }
115 return is_array(variable_get('content_profile_'. $type, FALSE));
116 }
117
118 /**
119 * Builds a list of available content types that are marked as content_profiles,
120 * and returns an array of content profile content types in the specified format.
121 *
122 * @param $op When set to 'types', content profile content types are returned
123 * as type objects. When set to 'names', only their type names
124 * are returned.
125 * @param $setting If set, only content types that have this setting activated are
126 * returned. Leave it NULL to get all content profile types.
127 */
128 function content_profile_get_types($op = 'types', $setting = NULL) {
129 $types = array();
130
131 foreach (node_get_types($op) as $type => $info) {
132 if (is_content_profile($type) && (!isset($setting) || content_profile_get_setting($type, $setting))) {
133 $types[$type] = $info;
134 }
135 }
136 return $types;
137 }
138
139 /**
140 * Implementation of hook_node_type():
141 * Rename or delete the settings variable if a type changes.
142 */
143 function content_profile_node_type($op, $info) {
144 switch ($op) {
145 case 'delete':
146 variable_del('content_profile_'. $info->type);
147 break;
148 case 'update':
149 if (!empty($info->old_type) && $info->old_type != $info->type) {
150 if (is_content_profile($info->old_type)) {
151 $settings = variable_get('content_profile_'. $info->old_type, array());
152 variable_del('content_profile_'. $info->old_type);
153 variable_set('content_profile_'. $info->type, $settings);
154 }
155 }
156 break;
157 }
158 }
159
160 /**
161 * Implementation of hook_form_alter().
162 */
163 function content_profile_form_alter(&$form, $form_state, $form_id) {
164 if ($form_id == 'node_type_form') {
165 $form['content_profile'] = array(
166 '#type' => 'fieldset',
167 '#title' => t('Node Profile'),
168 '#collapsible' => TRUE,
169 '#weight' => 32,
170 );
171 $form['content_profile']['content_profile'] = array(
172 '#type' => 'checkbox',
173 '#title' => t('Use this content type as a content_profile for users'),
174 '#default_value' => is_content_profile($form['#node_type']->type),
175 '#return_value' => array(),
176 );
177 }
178 else if (isset($form['#node']) && $form['#node']->type .'_node_form' == $form_id) {
179 if (is_content_profile($form['#node']) && user_access('administer nodes')) {
180 //$form['#validate'][] = 'content_profile_validate_profile';
181 //TODO: implement admin validation and support translations
182 }
183 }
184 }
185
186
187 /**
188 * Implementation of hook_user():
189 */
190 function content_profile_user($op, &$edit, &$account, $category = NULL) {
191 global $user;
192
193 switch ($op) {
194 case 'view':
195 $account->content['content_profile'] = content_profile_show_profiles($account->uid);
196 break;
197
198 case 'delete':
199 // retrieve profile node types to be deleted
200 $typenames = array();
201 foreach (node_get_types('names') as $typename => $visiblename) {
202 if (is_content_profile($typename)) {
203 $typenames[] = $typename;
204 //$typenames = array_merge($typenames, nodefamily_get_descendant_types($typename));
205 }
206 }
207
208 // Retrieve the matching profile nodes for this user by issueing an SQL
209 // query. node_load() doesn't work, because its own query still requires
210 // the user to be in the {user} table, which is not the case anymore.
211 // That node_load() doesn't work also means that node_delete() doesn't
212 // work, which is why we have to use _content_profile_node_delete() instead.
213 $cond = array();
214 $arguments = array();
215
216 foreach (content_profile_get_types() as $type => $type_info) {
217 $cond[] = "type = '%s'";
218 $arguments[] = $type;
219 }
220 $cond = implode(' OR ', $cond);
221 $arguments[] = $account->uid;
222
223 if ($cond) {
224 $result = db_query("SELECT * FROM {node} WHERE (". $cond .") AND uid = %d", $arguments);
225 while ($node = db_fetch_object($result)) {
226 _content_profile_node_delete($node);
227 }
228 }
229 break;
230 }
231 }
232
233 /**
234 * The original node_delete() function uses node_load() to get the $node object.
235 * Unfortunately, when a hook_user('delete') is called, node_load() doesn't
236 * work anymore because the user has already been deleted, and node_load()
237 * still expects the user to exist in the {user} table.
238 *
239 * So this is a modified copy of node_delete() that deletes a node without
240 * calling node_load(), taking the full $node object (as retrieved by a simple
241 * "SELECT * FROM {node}" query) instead of just the $nid.
242 */
243 function _content_profile_node_delete($node) {
244
245 // Copied over from node_load(), so that node_invoke('delete') gets
246 // the fully extended node object, like modules would expect:
247
248 if ($node->nid) {
249 // Call the node specific callback (if any) and piggy-back the
250 // results to the node or overwrite some values.
251 if ($extra = node_invoke($node, 'load')) {
252 foreach ($extra as $key => $value) {
253 $node->$key = $value;
254 }
255 }
256 if ($extra = node_invoke_nodeapi($node, 'load')) {
257 foreach ($extra as $key => $value) {
258 $node->$key = $value;
259 }
260 }
261 }
262
263 // Copied over from node_delete():
264
265 db_query('DELETE FROM {node} WHERE nid = %d', $node->nid);
266 db_query('DELETE FROM {node_revisions} WHERE nid = %d', $node->nid);
267
268 // Call the node-specific callback (if any):
269 node_invoke($node, 'delete');
270 node_invoke_nodeapi($node, 'delete');
271
272 // Clear the cache so an anonymous poster can see the node being deleted.
273 cache_clear_all();
274
275 // Remove this node from the search index if needed.
276 if (function_exists('search_wipe')) {
277 search_wipe($node->nid, 'node');
278 }
279 drupal_set_message(t('%title has been deleted.', array('%title' => $node->title)));
280 watchdog('content', '@type: deleted %title.', array('@type' => node_get_types('name', $node->type), '%title' => $node->title));
281 }
282
283 /**
284 * Implementation of hook_nodeapi().
285 */
286 function content_profile_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
287 global $last_nid;
288
289 if ($op == 'prepare' && is_content_profile($node) && !isset($node->nid) && !user_access('administer nodes')) {
290 // Check if this nodetype already exists
291 $result = db_query("SELECT n.nid AS nid FROM {node} n WHERE n.type = '%s' AND n.uid = %d AND n.language = '%s'", $node->type, $node->uid, $node->language);
292 if ($nid = db_result($result)) {
293 // This node already exists, redirect to edit page
294 drupal_goto('node/'. $nid .'/edit', 'destination=user/'. $node->uid);
295 }
296 }
297 else if ($op == 'alter' && is_content_profile($node->type) && isset($last_nid)) {
298 // Index themed node
299 $node->body = theme('node', $node, FALSE, TRUE); //TODO: check if still necessary
300 }
301 }
302
303 /**
304 * Returns the content_profiles' settings
305 * @param $type The content type to return settings for
306 * @param $return 'all' or one of the content_profile_available_settings(), e.g. user_edit, register or weight
307 */
308 function content_profile_get_settings($type, $return = 'all') {
309 $settings = variable_get('content_profile_'. $type, array());
310 $settings += content_profile_settings_info();
311 if ($return == 'all') {
312 return $settings;
313 }
314 return $settings[$return];
315 }
316
317 /**
318 * Saves the content_profile settings of a content type
319 */
320 function content_profile_set_settings($type, $settings) {
321 //cleanup the settings before saving
322 variable_set('content_profile_'. $type, $settings);
323 }
324
325 /**
326 * Returns an array, which defines the default value for each
327 * available setting
328 */
329 function content_profile_settings_info() {
330 return module_invoke_all('content_profile_settings');
331 }
332
333 /**
334 * Implementation of hook_content_profile_settings()
335 * Defines content profile settings and their default value
336 */
337 function content_profile_content_profile_settings() {
338 return array(
339 'weight' => 0,
340 'user_display' => 'teaser',
341 'edit_link' => 1,
342 'add_link' => 1,
343 );
344 }
345
346 /**
347 * Loads the node, like node_load but caches the results
348 */
349 function content_profile_load($type, $uid) {
350 static $cache = array();
351
352 if (!isset($cache[$type][$uid])) {
353 $cache[$type][$uid] = node_load(array('type' => $type, 'uid' => $uid));
354 }
355 return $cache[$type][$uid];
356 }
357
358 /**
359 * Returns an array suitable for use with drupal_render,
360 * that shows all content_profiles as configured by the admin
361 */
362 function content_profile_show_profiles($uid) {
363 global $user;
364
365 $content = array();
366 foreach (content_profile_get_types('names') as $type => $type_name) {
367 $node = content_profile_load($type, $uid);
368
369 if (($style = content_profile_get_settings($type, 'user_display')) && $node && node_access('view', $node)) {
370 $content['content_profile_'. $type] = array(
371 '#theme' => ($style == 'link') ? 'content_profile_display_link' : 'content_profile_display_view',
372 '#edit_link' => content_profile_get_settings($type, 'edit_link'),
373 '#uid' => $uid,
374 '#style' => $style,
375 '#content_type' => $type,
376 '#weight' => content_profile_get_settings($type, 'weight'),
377 '#suffix' => '<br />',
378 );
379 }
380 else if ($uid == $user->uid && user_access('create '. $type .' content') && content_profile_get_settings($type, 'add_link')) {
381 $content['content_profile_'. $type] = array(
382 '#theme' => 'content_profile_display_add_link',
383 '#uid' => $uid,
384 '#content_type' => $type,
385 '#weight' => content_profile_get_settings($type, 'weight'),
386 '#suffix' => '<br />',
387 );
388 }
389 $content['#prefix'] = '<p id="content-profile-view">';
390 $content['#suffix'] = '</p>';
391 }
392 return $content;
393 }
394
395 /**
396 * Implementation of hook_theme()
397 */
398 function content_profile_theme() {
399 return array(
400 'content_profile_display_view' => array(
401 'template' => 'content_profile-display-view',
402 'arguments' => array('element' => NULL),
403 'file' => 'content_profile.theme.inc',
404 ),
405 'content_profile_display_add_link' => array(
406 'file' => 'content_profile.theme.inc',
407 ),
408 'content_profile_display_link' => array(
409 'file' => 'content_profile.theme.inc',
410 ),
411 'content_profile_display_tab_view' => array(
412 'file' => 'content_profile.theme.inc',
413 ),
414 'content_profile_display_tab_edit' => array(
415 'file' => 'content_profile.theme.inc',
416 ),
417 );
418 }

  ViewVC Help
Powered by ViewVC 1.1.2