/[drupal]/contributions/modules/relations/relations.module
ViewVC logotype

Contents of /contributions/modules/relations/relations.module

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


Revision 1.16 - (show annotations) (download) (as text)
Mon Aug 31 15:46:20 2009 UTC (2 months, 4 weeks ago) by arto
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-BETA1, HEAD
Changes since 1.15: +13 -0 lines
File MIME type: text/x-php
Implemented new UI settings for hiding the 'Relations' node tab or the 'Related content' fieldset.
1 <?php
2 // $Id$
3
4 //////////////////////////////////////////////////////////////////////////////
5 // Module settings
6
7 define('RELATIONS_REPOSITORY', 'relations');
8 define('RELATIONS_PREDICATE', 'http://www.w3.org/2000/01/rdf-schema#seeAlso');
9
10 //////////////////////////////////////////////////////////////////////////////
11 // Core API hooks
12
13 /**
14 * Implementation of hook_help().
15 */
16 function relations_help($path, $arg = NULL) {
17 switch ($path) {
18 case 'node/%/relations#table':
19 return '<p>' . t('To create a new relationship, type in the title or URL of another content item in the textbox above. You must have editor privileges for either the source or target item, and at least reader privileges for the other item.') . '</p>';
20 }
21 }
22
23 /**
24 * Implementation of hook_perm().
25 */
26 function relations_perm() {
27 return array(
28 'view node relations',
29 'create node relations',
30 'delete node relations',
31 );
32 }
33
34 /**
35 * Implementation of hook_menu().
36 */
37 function relations_menu() {
38 return array(
39 'node/%node/relations' => array(
40 'title' => 'Relations',
41 'description' => 'List, edit, or create node relationships.',
42 'type' => MENU_LOCAL_TASK,
43 'access callback' => 'relations_menu_access',
44 'access arguments' => array(1, 'view node relations', TRUE),
45 'page callback' => 'drupal_get_form',
46 'page arguments' => array('relations_node_form', 1),
47 'file' => 'relations.pages.inc',
48 'weight' => 3,
49 ),
50 'node/%node/relations/autocomplete' => array(
51 'title' => 'Relations autocomplete',
52 'type' => MENU_CALLBACK,
53 'access callback' => 'relations_menu_access',
54 'access arguments' => array(1, 'create node relations', TRUE),
55 'page callback' => 'relations_node_title_autocomplete',
56 'page arguments' => array(1),
57 'file' => 'relations.pages.inc',
58 ),
59 'node/%node/relations/delete/%node' => array(
60 'title' => 'Delete relation',
61 'type' => MENU_CALLBACK,
62 'access callback' => 'relations_menu_access',
63 'access arguments' => array(1, 'delete node relations', TRUE),
64 'page callback' => 'drupal_get_form',
65 'page arguments' => array('relations_node_delete', 1, 4),
66 'file' => 'relations.pages.inc',
67 ),
68
69 // AHAH handlers for unsaved nodes
70 'node/add/relations/autocomplete' => array(
71 'title' => 'Relations autocomplete (for unsaved nodes)',
72 'type' => MENU_CALLBACK,
73 'access callback' => 'relations_menu_access',
74 'access arguments' => array(NULL, 'view node relations', TRUE),
75 'page callback' => 'relations_node_title_autocomplete',
76 'page arguments' => array(NULL),
77 'file' => 'relations.pages.inc',
78 ),
79 'node/add/relations/create' => array(
80 'title' => 'Add relation (for unsaved nodes)',
81 'type' => MENU_CALLBACK,
82 'access callback' => 'relations_menu_access',
83 'access arguments' => array(NULL, 'view node relations', TRUE),
84 'page callback' => 'relations_node_session_create',
85 'page arguments' => array(),
86 'file' => 'relations.pages.inc',
87 ),
88 'node/add/relations/delete/%node' => array(
89 'title' => 'Delete relation (for unsaved nodes)',
90 'type' => MENU_CALLBACK,
91 'access callback' => 'relations_menu_access',
92 'access arguments' => array(NULL, 'view node relations', TRUE),
93 'page callback' => 'relations_node_session_delete',
94 'page arguments' => array(4),
95 'file' => 'relations.pages.inc',
96 ),
97
98 // Administer >> Site configuration >> RDF settings >> Relations
99 'admin/settings/rdf/relations' => array(
100 'title' => 'Relations',
101 'description' => 'Settings for the Relations API module.',
102 'access arguments' => array('administer site configuration'),
103 'page callback' => 'drupal_get_form',
104 'page arguments' => array('relations_admin_settings'),
105 'file' => 'relations.admin.inc',
106 ),
107 );
108 }
109
110 /**
111 * Implementation of hook_menu_alter().
112 */
113 function relations_menu_alter(&$items) {
114 if (!variable_get('relations_ui_node_tab', '1')) {
115 unset($items['node/%node/relations']);
116 }
117 }
118
119 /**
120 * Implementation of hook_block().
121 */
122 function relations_block($op = 'list', $delta = 0, $edit = array()) {
123 $node_types = node_get_types('names');
124
125 switch ($op) {
126 case 'list':
127 $blocks = array(
128 'relations' => array(
129 'info' => t('Relations'),
130 'region' => 'right',
131 'weight' => -3,
132 'cache' => BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_USER,
133 ),
134 );
135 foreach (relations_get_node_types() as $node_type) {
136 $blocks[$node_type] = array(
137 'info' => t('Relations: !type', array('!type' => $node_types[$node_type])),
138 'region' => 'right',
139 'weight' => -3,
140 'cache' => BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_USER,
141 );
142 }
143 return $blocks;
144
145 case 'view':
146 $block = array();
147 if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) != 'edit') {
148 $node = node_load(arg(1));
149
150 switch ($delta) {
151 case 'relations':
152 $block['subject'] = t('Related content');
153 $block['content'] = theme('relations_node_block', $node);
154 break;
155 default:
156 if (array_search($delta, relations_get_node_types($node)) && isset($node_types[$delta])) {
157 $block['subject'] = t('Related content: !type', array('!type' => $node_types[$delta]));
158 $block['content'] = theme('relations_node_block', $node, array('type' => $delta));
159 }
160 break;
161 }
162 }
163 return $block;
164 }
165 }
166
167 /**
168 * Implementation of hook_forms().
169 */
170 function relations_forms() {
171 return array(
172 'relations_node_form' => array(
173 'callback' => 'relations_node_form',
174 ),
175 );
176 }
177
178 /**
179 * Implementation of hook_theme()
180 */
181 function relations_theme() {
182 return array(
183 'relations_node_form' => array(
184 'arguments' => array('node' => NULL),
185 'file' => 'relations.pages.inc',
186 ),
187 'relations_node_table' => array(
188 'arguments' => array('node' => NULL),
189 'file' => 'relations.pages.inc',
190 ),
191 'relations_node_block' => array(
192 'arguments' => array('node' => NULL),
193 'file' => 'relations.pages.inc',
194 ),
195 'relations_node_list' => array(
196 'arguments' => array('nodes' => NULL),
197 'file' => 'relations.pages.inc',
198 ),
199 'relations_admin_settings' => array(
200 'arguments' => array('form' => NULL),
201 'file' => 'relations.admin.inc',
202 ),
203 );
204 }
205
206 /**
207 * Implementation of hook_form_alter().
208 *
209 * @see relations_nodeapi()
210 */
211 function relations_form_alter(&$form, $form_state, $form_id) {
212 if (isset($form['type']) && isset($form['#node'])) {
213 $node = $form['#node'];
214
215 if ($form['type']['#value'] .'_node_form' == $form_id && relations_is_node_type_enabled($node->type)) {
216 if (!variable_get('relations_ui_node_edit', '1')) {
217 return; // configured at <admin/settings/rdf/relations>
218 }
219
220 $form['relations'] = array(
221 '#type' => 'fieldset',
222 '#access' => user_access('create node relations'),
223 '#title' => t('Related content'),
224 '#collapsible' => TRUE,
225 '#collapsed' => TRUE,
226 '#prefix' => '<div class="relations">',
227 '#suffix' => '</div>',
228 '#weight' => 20,
229 );
230 $form['relations']['relations_blocks'] = array(
231 '#type' => 'checkboxes',
232 '#title' => t('Enabled related content types'),
233 '#default_value' => relations_get_node_types($node),
234 '#options' => array_map('t', array_intersect_key(node_get_types('names'), relations_get_node_types())),
235 '#description' => t('Select which types of related content you wish to display when this node is viewed.'),
236 );
237
238 module_load_include('inc', 'relations', 'relations.pages');
239 $form['relations']['relations_table'] = relations_node_form(array(), $node, TRUE);
240 }
241 }
242 }
243
244 /**
245 * Implementation of hook_nodeapi().
246 */
247 function relations_nodeapi(&$node, $op, $arg = 0) {
248 if (relations_is_node_type_enabled($node->type)) {
249 switch ($op) {
250 case 'prepare':
251 if (empty($_POST)) {
252 $_SESSION['relations'] = array('create' => array(), 'delete' => array());
253 }
254 $node->relations_blocks = relations_get_node_types($node);
255 break;
256 case 'insert':
257 case 'update':
258 if (!empty($_SESSION['relations']['delete'])) {
259 foreach ($_SESSION['relations']['delete'] as $nid => $title) {
260 relations_api_delete($node->nid, $nid);
261 }
262 }
263 if (!empty($_SESSION['relations']['create'])) {
264 foreach ($_SESSION['relations']['create'] as $nid => $title) {
265 relations_api_create($node->nid, $nid);
266 }
267 }
268 unset($_SESSION['relations']);
269 if (isset($node->relations_blocks)) {
270 $node->relations_blocks = array_filter($node->relations_blocks, 'is_string');
271 variable_set('relations_blocks_node_'. $node->nid, $node->relations_blocks);
272 }
273 break;
274 case 'delete':
275 variable_del('relations_blocks_node_'. $node->nid);
276 break;
277 }
278 }
279 }
280
281 //////////////////////////////////////////////////////////////////////////////
282 // Picker API hooks
283
284 function relations_picker_access($node2) {
285 // When adding relations to an existing node:
286 if (!empty($_SERVER['HTTP_REFERER']) && preg_match('!node/(\d+)/!', $_SERVER['HTTP_REFERER'], $matches)) {
287 $node1 = node_load((int)$matches[1]);
288 return relations_allowed($node1, $node2);
289 }
290 // When adding relations to a node to be created:
291 if (!empty($_SESSION['relations'])) {
292 return relations_allowed(TRUE, $node2);
293 }
294 }
295
296 //////////////////////////////////////////////////////////////////////////////
297 // Relations API implementation
298
299 function relations_menu_access($node, $perm) {
300 return user_access($perm) && (empty($node) || relations_is_node_type_enabled($node->type));
301 }
302
303 function relations_is_node_type_enabled($type) {
304 return array_search($type, relations_get_node_types());
305 }
306
307 function relations_get_node_types($node = NULL) {
308 return isset($node->nid) ?
309 variable_get('relations_blocks_node_'. $node->nid, relations_get_node_types(NULL)) :
310 array_filter(variable_get('relations_node_types', array()), 'is_string');
311 }
312
313 function relations_get_predicate() {
314 return variable_get('relations_predicate', RELATIONS_PREDICATE);
315 }
316
317 function relations_get_predicates($op = NULL) {
318 switch ($op) {
319 case 'keys':
320 return array_combine(array_keys(relations_get_predicates()), array_fill(0, count(relations_get_predicates()), ''));
321 default:
322 return array(
323 relations_get_predicate() => (object)array('title' => t('See also'), 'uri' => relations_get_predicate(), 'bidirectional' => TRUE),
324 );
325 }
326 }
327
328 function relations_rdf_options() {
329 return array('repository' => RELATIONS_REPOSITORY);
330 }
331
332 function relations_node_url($nid) {
333 return url('node/'. $nid, array('alias' => TRUE, 'absolute' => TRUE));
334 }
335
336 function relations_api_query($url) {
337 // TODO: this breaks encapsulation; should probably implement multi-queries directly in RDF API.
338 return array_merge(
339 rdf_query(rdf_uri($url), NULL, NULL, relations_rdf_options())->to_array(),
340 rdf_query(NULL, NULL, rdf_uri($url), relations_rdf_options())->to_array());
341 }
342
343 function relations_api_lookup($node, array $options = array()) {
344 global $user;
345 $account = empty($options['user']) ? $user : (is_object($options['user']) ? $options['user'] : user_load($options['user']));
346 $nid = is_object($node) ? $node->nid : (int)$node;
347
348 // Support for filtering related nodes by one or more content types:
349 if (!empty($options['type'])) {
350 $options['type'] = is_array($options['type']) ? $options['type'] : array($options['type']);
351 }
352
353 $nodes = array();
354 $results = relations_api_query(relations_node_url($nid));
355 foreach ($results as $triple) {
356 list($s, $p, $o) = $triple;
357 if ((preg_match('!node/'. $nid .'$!', (string)$s) && preg_match('!node/(\d+)$!', (string)$o, $matches)) ||
358 (preg_match('!node/'. $nid .'$!', (string)$o) && preg_match('!node/(\d+)$!', (string)$s, $matches))) {
359 if (($node = node_load($matches[1])) && node_access('view', $node, $account)) {
360 if (empty($options['type']) || in_array($node->type, $options['type'])) {
361 $nodes[$node->nid] = $node;
362 }
363 }
364 }
365 }
366 return $nodes;
367 }
368
369 function relations_api_create($node1, $node2, array $options = array()) {
370 $nid1 = is_object($node1) ? $node1->nid : (int)$node1;
371 $nid2 = is_object($node2) ? $node2->nid : (int)$node2;
372
373 // Make sure we never insert duplicate statements:
374 if (($existing = relations_api_lookup($nid1, $options)) && isset($existing[$nid2])) {
375 return TRUE;
376 }
377
378 $url1 = rdf_uri(relations_node_url($nid1));
379 $url2 = rdf_uri(relations_node_url($nid2));
380 return rdf_insert($url1, relations_get_predicate(), $url2, relations_rdf_options());
381 }
382
383 function relations_api_delete($node1, $node2, array $options = array()) {
384 $nid1 = is_object($node1) ? $node1->nid : (int)$node1;
385 $nid2 = is_object($node2) ? $node2->nid : (int)$node2;
386
387 $url1 = rdf_uri(relations_node_url($nid1));
388 $url2 = rdf_uri(relations_node_url($nid2));
389 rdf_delete($url1, relations_get_predicate(), $url2, relations_rdf_options());
390 rdf_delete($url2, relations_get_predicate(), $url1, relations_rdf_options());
391 return TRUE;
392 }
393
394 function relations_allowed($node1, $node2) {
395 // Must have edit access to either the source or destination node, and
396 // view access to the target node (view access to the source node is
397 // implied):
398 $editor1 = is_object($node1) ? node_access('update', $node1) : (bool)$node1;
399 $editor2 = node_access('update', $node2);
400 $reader2 = node_access('view', $node2);
401 return ($editor1 || $editor2) && $reader2;
402 }

  ViewVC Help
Powered by ViewVC 1.1.2