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

Contents of /contributions/modules/weight/weight.module

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


Revision 1.35 - (show annotations) (download) (as text)
Mon Jan 26 00:18:23 2009 UTC (10 months ago) by nancyw
Branch: MAIN
CVS Tags: HEAD
Changes since 1.34: +36 -16 lines
File MIME type: text/x-php
#320929 by NancyDru for David Lesieur - Simplify administration.
1 <?php
2 // $Id: weight.module,v 1.34 2009/01/25 23:06:41 nancyw Exp $
3 /**
4 * @file
5 * This module uses the sticky column of the node table
6 * to add weighting to nodes.
7 */
8
9 /**
10 * Implementation of hook_help().
11 */
12 function weight_help($path, $args) {
13 switch ($path) {
14 case 'admin/setting/weight':
15 case 'admin/modules#description':
16 return t('Add weight-based sorting to nodes.');
17 case 'admin/help#weight':
18 return t('<h3>Description:</h3><p>The weight module adds a weight option to enabled node types. It uses the "sticky" field in the database to store weights as well as sticky information (so that feature is not lost). Nodes will be sorted first by stickiness, then by weight (lightest to heaviest), then by creation date.</p>
19 <h4>Setup:</h4><p>To enable weight sorting on existing nodes, visit the <a href="@setup">weight db setup page</a> and click "Setup Database" to convert old sticky values to new weight-encoded values for proper sorting.</p>
20 <h4>Permissions:</h4><p>Users with "administer nodes" permission will always be able to adjust weight for enabled node types. However, enabling "assign node weight" will allow non-node-admin users to adjust weight on their own nodes. Find these settings <a href="@access">here</a>.</p>
21 <h4>Bulk weight management</h4><p>You may easily manage the weight of multiple nodes simultaneously by using the <a href="@node_admin"> node admin page</a>.</p>',
22 array(
23 '@setup' => url('admin/settings/weight/setup'),
24 '@access' => url('admin/user/permissions'),
25 '@node_admin' => url('admin/content/node')
26 )
27 );
28 }
29 }
30
31 function weight_perm() {
32 return array('assign node weight');
33 }
34
35 /**
36 * Implementation of hook_menu().
37 */
38 function weight_menu() {
39 $items = array();
40
41 // Ajax callback for weight changer page.
42 $items['admin/node/weight/_weight_change'] = array(
43 'page callback' => '_weight_change',
44 'access arguments' => array('administer nodes'),
45 'type' => MENU_CALLBACK
46 );
47
48 // Top level settings.
49 $items['admin/settings/weight'] = array(
50 'title' => 'Weight',
51 'access arguments' => array('administer site configuration'),
52 'description' => 'Add weight-based sorting to nodes.',
53 'page callback' => 'drupal_get_form',
54 'page arguments' => array('weight_settings_form'),
55 );
56
57 // 2nd level nav (tabs).
58 /* $items['admin/settings/weight/settings'] = array(
59 'title' => 'Settings',
60 'access arguments' => array('administer site configuration'),
61 'type' => MENU_DEFAULT_LOCAL_TASK
62 );
63
64 $items['admin/settings/weight/setup'] = array(
65 'title' => 'Db setup',
66 'access arguments' => array('administer site configuration'),
67 'page callback' => 'drupal_get_form',
68 'page arguments' => array('weight_setup_form'),
69 'type' => MENU_LOCAL_TASK,
70 'weight' => 4
71 );
72
73 // 3rd level.
74 $items['admin/settings/weight/setup/enable'] = array(
75 'title' => 'Enable',
76 'access arguments' => array('administer site configuration'),
77 'type' => MENU_DEFAULT_LOCAL_TASK,
78 'weight' => -2
79 );
80
81 $items['admin/settings/weight/setup/disable'] = array(
82 'title' => 'Disable',
83 'access arguments' => array('administer site configuration'),
84 'page callback' => 'drupal_get_form',
85 'page arguments' => array('weight_disable_form'),
86 'type' => MENU_LOCAL_TASK,
87 'weight' => 2
88 ); /* */
89
90 return $items;
91 }
92
93 function weight_nodeapi(&$node, $op) {
94 switch ($op) {
95 case 'presave':
96 // Non-weighted nodes have a weight of zero.
97 if (is_null($node->node_weight)) {
98 $node->node_weight = 0;
99 }
100
101 // If the admin wants to use the menu weight, see if there is one.
102 if (variable_get('weight_use_menu', FALSE)) {
103 $node->node_weight = (isset($node->menu['link_title']) && !empty($node->menu['link_title'])) ? $node->menu['weight'] : $node->node_weight;
104 }
105
106 // Here we're 'encoding' weight into the sticky value for the database
107 // stickiness is the inverse of weight
108 // - stickiness is sorted DESC while weight is sorted ASC so we invert
109 // the weight before saving... if sticky box is checked, subtract weight
110 // from 100; unweighted sticky nodes will have a value of 100.
111 _weight_encode($node);
112 break;
113
114 case 'load':
115 _weight_decode($node);
116 break;
117 }
118 }
119
120 /**
121 * Implementation of hook_form_alter().
122 *
123 * This is where we tweak the admin/content/node to include our weight
124 * selector; hide the 'sticky' filter (it won't work when using weight module),
125 * and add some help text to the form.
126 */
127 function weight_form_alter(&$form, $form_state, $form_id) {
128 $weight_node_types = variable_get('weight_node_types', array_flip(node_get_types('names')));
129
130 $weight_node_type_names = array();
131 foreach ($weight_node_types as $type) {
132 $weight_node_type_names[] = node_get_types('name', $type);
133 }
134
135 if ($form_id == 'node_admin_content') {
136 // The admin node page does not use the nodeapi for getting lists of nodes, so
137 // I never have a chance to convert the sticky flag to 0/1. and trying to
138 // filter on that field will not work. Therefore, I am going to hide the
139 // 'filter on sticky status' altogether when weight_module is enabled
140 unset($form['filters']['status']['status']['#options']['sticky-1']);
141 unset($form['filters']['status']['status']['#options']['sticky-0']);
142 $form['weight_help'] = array(
143 '#type' => 'markup',
144 '#value' => t('<strong>Note:</strong> When the weight module is enabled,
145 it is not possible to filter based on sticky status.')
146 );
147
148 // I can't add a table header for weight, so instead I'm going to explain
149 // the weight dropdown to the user. Also, to position my help text
150 // appropriately, I'm using this '#suffix' hack rather than adding
151 // a form property as i'd like to do.
152 $form['options']['#suffix'] .= t('<strong>Weight:</strong> To change the weight of a node, select a value from the corresponding dropdown box under <i>@operations</i>. Node weights are submitted immediately. Selectors are only available for node types configured on the <a href="@weight_admin">weight admin page</a>.',
153 array(
154 '@weight_admin' => url('admin/settings/weight'),
155 '@operations' => t('Operations'),
156 )
157 );
158
159 // Add weight selector under the operations section of the admin node
160 // overview page (admin/content/node).
161 if (!empty($form['admin']['operations'])) {
162 foreach ($form['admin']['operations'] as $nid => $title) {
163 // only add weight selector if weight is enabled for this node type
164 if (in_array($form['admin']['name'][$nid]['#value'], $weight_node_type_names) ) {
165 $form['admin']['operations'][$nid]['weight_selector']['#value'] = weight_node_selector($nid);
166 }
167 }
168 }
169 }
170
171 // Node edit page weight selector.
172 if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
173 if (user_access('assign node weight') || user_access('administer nodes')) {
174 $node = $form['#node'];
175 if (in_array($node->type, $weight_node_types)) {
176 $range = variable_get('weight_range', 20);
177 $position = variable_get('weight_position', 0);
178 $where = 'weight_form';
179
180 if ($position == 10 && user_access('administer nodes')) {
181 // We will add it to the Workflow fieldset.
182 $where = 'options';
183 }
184 else {
185 // Add the node weight selector fieldset.
186 $form['weight_form'] = array(
187 '#type' => 'fieldset',
188 '#title' => t('Node Weight'),
189 '#collapsible' => TRUE,
190 '#collapsed' => ($node->node_weight == 0),
191 '#weight' => $position,
192 );
193 }
194
195 $form[$where]['node_weight'] = array(
196 '#type' => 'weight',
197 '#title' => t('Weight'),
198 '#default_value' => (int)$node->node_weight,
199 '#delta' => $range,
200 '#description' => t('In a node list context (such as the front page or term pages), list items (e.g. "teasers") will be ordered by "stickiness" then by "node weight" then by "authored on" datestamp. Items with a lower (lighter) node weight value will appear above those with a higher (heavier) value.'),
201 );
202
203 if (variable_get('weight_use_menu', FALSE)) {
204 $form['weight_form']['node_weight']['#description'] .= '<br /> '. t('<strong>Note</strong>: If this node is used in a menu, then this weight will be ignored.');
205 }
206 }
207 }
208 }
209 }
210
211 function weight_setup_form() {
212 $count = 0;
213 $weight_node_types = array_filter(variable_get('weight_node_types', array()));
214 if (!empty($weight_node_types)) {
215 $placeholders = db_placeholders($weight_node_types, 'text');
216 $count = db_result(db_query("SELECT COUNT(n.nid) FROM {node} n WHERE n.sticky IN (0,1) AND n.type IN ($placeholders)", $weight_node_types));
217 }
218
219 $form['information'] = array(
220 '#type' => 'markup',
221 '#value' => t("<p>The weight module uses the node table's 'sticky' column to store weight information for each node. New and updated nodes will automatically have their sticky and weight information remapped. However if you have pre-existing nodes, you will need to update your database so that these nodes sort correctly with new nodes.</p><p>@count nodes need to be updated.</p>", array('@count' => $count))
222 );
223
224 // Only provide the submit button if there are actual nodes needing the update.
225 if ($count) {
226 $form['submit'] = array(
227 '#type' => 'submit',
228 '#value' => t('Setup Database'),
229 );
230 }
231 return $form;
232 }
233
234 function weight_setup_form_submit($form, &$form_state) {
235 weight_old_nodes();
236 $form_state['redirect'] = 'admin/settings/weight';
237 }
238
239 function weight_disable_form() {
240 $count = 0;
241 $weight_node_types = array_filter(variable_get('weight_node_types', array()));
242 if (empty($weight_node_types)) {
243 $count = db_result(db_query("SELECT COUNT(n.nid) FROM {node} n WHERE n.sticky NOT IN (0,1)", $weight_node_types));
244 }
245 else {
246 $placeholders = db_placeholders($weight_node_types, 'text');
247 $count = db_result(db_query("SELECT COUNT(n.nid) FROM {node} n WHERE n.sticky NOT IN (0,1) AND n.type NOT IN ($placeholders)", $weight_node_types));
248 }
249
250 $form['information'] = array(
251 '#type' => 'markup',
252 '#value' => t("<p>Before disabling the weight module, you will want to click this button to change the database back to Drupal's conventional sticky system.</p><p>@count nodes need to be updated.</p>", array('@count' => $count)),
253 );
254
255 // Only provide the submit button if there are actual nodes needing the update.
256 if ($count) {
257 $form['warning'] = array(
258 '#type' => 'markup',
259 '#value' => t('<p><strong>NOTE: Clicking this button will erase any node weights that have been set.</strong></p>'),
260 );
261 $form['submit'] = array(
262 '#type' => 'submit',
263 '#value' => t('Remove weights'),
264 );
265 }
266 return $form;
267 }
268
269 function weight_disable_form_submit($form, &$form_state) {
270 weight_disable();
271 $form_state['redirect'] = 'admin/settings/weight';
272 }
273
274 function weight_settings_form() {
275 $form = array();
276 $types = node_get_types('names');
277
278 $form['weight_range'] = array(
279 '#type' => 'select',
280 '#title' => t('Node Weight Range'),
281 '#default_value' => variable_get('weight_range', 20),
282 '#options' => array(5 => 5, 10 => 10, 20 => 20, 30 => 30, 40 => 40),
283 '#description' => '<p>'. t('This will be the +/- range for node weight.') .'</p>',
284 );
285
286 $form['weight_use_menu'] = array(
287 '#type' => 'checkbox',
288 '#title' => t('Use Menu Weight'),
289 '#default_value' => variable_get('weight_use_menu', FALSE),
290 '#description' => '<p>'. t('If the node has not been weighted, should we use the menu item weight?') .'</p>',
291 );
292
293 $form['weight_position'] = array(
294 '#type' => 'weight',
295 '#delta' => 10,
296 '#title' => t('Weight selector position weight'),
297 '#default_value' => variable_get('weight_position', 0),
298 '#description' => '<p>'. t('This controls where the selection for node weight goes on the node edit form. If the position is 10 and the user has "administer nodes" permission, it will be added into the "Workflow options."') .'</p>',
299 );
300
301 $form['weight_node_types'] = array(
302 '#type' => 'checkboxes',
303 '#title' => t('Display On'),
304 '#default_value' => variable_get('weight_node_types', $types),
305 '#options' => $types,
306 '#description' => '<p>'. t('Add node weighting to these content types.</p>
307 <p><i>Note:</i> Unselecting a node type after having changed weights
308 for nodes of that type will leave these nodes with the current weight.
309 You may want to check the <a href="@posts_page">content page</a> before
310 unsetting any node types.', array( '@posts_page' => url('admin/content/node'))
311 ) .'</p>',
312 );
313
314 $form['submit'] = array(
315 '#type' => 'submit',
316 '#value' => t('Update'),
317 );
318 return $form;
319 }
320
321 function weight_settings_form_submit($form, &$form_state) {
322 $before = array_filter(variable_get('weight_node_types', array()));
323 $after = array_filter($form_state['values']['weight_node_types']);
324 $del = array_diff($before, $after);
325 $add = array_diff($after, $before);
326 if ($add) {
327 weight_old_nodes($add);
328 }
329 if ($del) {
330 weight_disable($del);
331 }
332 variable_set('weight_range', $form_state['values']['weight_range']);
333 variable_set('weight_node_types', $after);
334 variable_set('weight_position', $form_state['values']['weight_position']);
335 drupal_set_message(t('Settings updated.'));
336 }
337
338 /**
339 * Update the sticky value of existing nodes if they are enabled for weights.
340 * This ensures that they will sort correctly.
341 */
342 function weight_old_nodes($weight_node_types = array()) {
343 if ($weight_node_types) {
344 drupal_set_message(t('Enabling weight for: !types', array('!types' => implode(', ', $weight_node_types))));
345 }
346 else {
347 $weight_node_types = array_filter(variable_get('weight_node_types', array()));
348 }
349 if ($weight_node_types) {
350 $placeholders = db_placeholders($weight_node_types, 'text');
351 db_query("UPDATE {node} n SET n.sticky = 100 WHERE n.sticky = 1 AND n.type IN ($placeholders)", $weight_node_types);
352 $count = db_affected_rows();
353 db_query("UPDATE {node} n SET n.sticky = -100 WHERE n.sticky = 0 AND n.type IN ($placeholders)", $weight_node_types);
354 $count += db_affected_rows();
355 drupal_set_message(t('@count nodes weight enabled.', array('@count' => $count)));
356 }
357 }
358
359 /**
360 * Set nodes back to normal sticky values if they are not enabled for weights.
361 */
362 function weight_disable($weight_node_types = array()) {
363 if ($weight_node_types) {
364 drupal_set_message(t('Disabling weight for: !types', array('!types' => implode(', ', $weight_node_types))));
365 }
366 else {
367 $weight_node_types = array_filter(variable_get('weight_node_types', array()));
368 }
369 if ($weight_node_types) {
370 $placeholders = db_placeholders($weight_node_types, 'text');
371 db_query("UPDATE {node} n SET n.sticky = 1 WHERE n.sticky > 1 AND n.type NOT IN ($placeholders)", $weight_node_types);
372 $count = db_affected_rows();
373 db_query("UPDATE {node} n SET n.sticky = 0 WHERE n.sticky < 0 AND n.type NOT IN ($placeholders)", $weight_node_types);
374 $count += db_affected_rows();
375 }
376 else {
377 db_query("UPDATE {node} n SET n.sticky = 1 WHERE n.sticky > 1");
378 $count = db_affected_rows();
379 db_query("UPDATE {node} n SET n.sticky = 0 WHERE n.sticky < 0");
380 $count += db_affected_rows();
381 }
382 drupal_set_message(t('@count nodes weight disabled.', array('@count' => $count)));
383 }
384
385 /**
386 * Generate JS code for selecting individual node weights on admin page
387 */
388 function weight_node_selector($nid) {
389 static $js_included;
390
391 if (!$js_included) {
392 $path = drupal_get_path('module', 'weight');
393 drupal_add_js($path .'/httpRequest.js', 'module', 'header', TRUE);
394 $js_included = TRUE;
395 drupal_add_css($path .'/weight.css');
396 }
397
398 $selector_template = "\n"."<form><select style=\"margin: 0;\"
399 onchange='httpRequest(\"GET\", \"" . base_path() .
400 "admin/node/weight/_weight_change/\" + [NID] + \"/\" +
401 this.options[this.selectedIndex].value,true)' >";
402
403 $node = node_load($nid);
404 // Convert to our weight range.
405 $weight = $node->node_weight;
406 // ugly bit of javascript we use for each dropdown to submit weight changes
407 // in the background. Relies on even uglier httpRequest.js file that comes
408 // with this module. Ironically, Ajax makes me feel dirty.
409
410 $weight_range = variable_get('weight_range', 20);
411 for ($i = 0 - $weight_range; $i <= $weight_range; ++$i) {
412 $selector_template .= "<option value='$i'>$i</option>";
413 }
414 $selector_template .= '</select></form>';
415 $weight_selector = $selector_template;
416 // TODO: need node weight to be able to choose this!
417 $weight_selector = preg_replace("/(value='$weight')/", "$1 selected='selected'", $weight_selector);
418 $weight_selector = preg_replace("/\[NID\]/", $nid, $weight_selector);
419 $weight_selector = '<div class="weight_selector">'. $weight_selector .'</div>';
420 return $weight_selector;
421 }
422
423 // Ajax callback for weight manager page.
424 function _weight_change($nid, $weight) {
425 // Doing it this way preserves the revision information.
426 $node = node_load($nid);
427 $node->node_weight = $weight;
428
429 _weight_encode($node);
430
431 node_save($node);
432 }
433
434 // Convert our weight to 'encoded' sticky value for DB.
435 function _weight_encode(&$node) {
436 if ($node->sticky) {
437 $node->sticky = 100 - $node->node_weight;
438 }
439 // Unweighted non-sticky nodes will have a value of -100.
440 else {
441 $node->sticky = -($node->node_weight + 100);
442 }
443 }
444
445 // Convert our weight back out of sticky.
446 function _weight_decode(&$node) {
447 // $x = $node->sticky;
448 if ($node->sticky > 0) {
449 $node->node_weight = $node->sticky == 1 ? 0 : (100 - $node->sticky);
450 $node->sticky = 1;
451 }
452 else {
453 $node->node_weight = $node->sticky == 0 ? 0 : -($node->sticky + 100);
454 $node->sticky = 0;
455 }
456 // drupal_set_message("For node $node->nid, $x becomes sticky: $node->sticky and weight: $node->node_weight.");
457 }
458
459 /**
460 * Implementation of hook_views_api().
461 */
462 function weight_views_api() {
463 return array(
464 'api' => 2,
465 'path' => drupal_get_path('module', 'weight'),
466 );
467 }
468
469 /**
470 * Implementation of hook_theme()
471 */
472 function weight_theme() {
473 return array(
474 'weight_view_weight_form' => array(
475 'arguments' => array('form' => NULL),
476 'template' => 'weight-view-weight-form',
477 ),
478 );
479 }
480
481 /**
482 * Prepare the weight form for its template file.
483 */
484 function template_preprocess_weight_view_weight_form(&$vars) {
485 $vars['header'] = $vars['form']['#variables']['header'];
486 $vars['class'] = $vars['form']['#variables']['class'];
487 $vars['id'] = $vars['form']['#variables']['id'];
488 $vars['fields'] = $vars['form']['#variables']['fields'];
489 foreach ($vars['form']['rows'] as $count => $item) {
490 if (is_numeric($count)) {
491 foreach ($item as $field => $value) {
492 if (substr($field, 0, 1) != '#') {
493 if (substr($field, 0, 6) == 'weight') {
494 $value['#attributes']['class'] = 'weight_dragger';
495 }
496 $vars['rows'][$count][$field] = drupal_render($value);
497 }
498 }
499 }
500 }
501 unset($vars['form']['rows']);
502 $vars['submit'] = drupal_render($vars['form']);
503 }

  ViewVC Help
Powered by ViewVC 1.1.2