Parent Directory
|
Revision Log
|
Revision Graph
fixed bug with tagnode maintenance: fixing tagnodes was erroneously creating new node
| 1 | <?php |
| 2 | // $Id: tagnode.module,v 1.9 2006/02/28 02:16:11 dado Exp $ |
| 3 | /* |
| 4 | * Created on Jul 15, 2005 |
| 5 | * by David Donohue (dado@drupal.org) |
| 6 | */ |
| 7 | |
| 8 | /** |
| 9 | * hook_form_alter implementation |
| 10 | */ |
| 11 | function tagnode_form_alter($form_id, &$form) { |
| 12 | if (isset($form["type"])) { |
| 13 | $node_type = $form["type"]["#value"]; |
| 14 | |
| 15 | if (isset($form["#node"])) { |
| 16 | $node = $form["#node"]; |
| 17 | } |
| 18 | |
| 19 | //Node Settings form was submitted: add tagnode select box |
| 20 | if( $node_type."_node_settings" == $form_id) { |
| 21 | $addform = _make_tagnode_vocab_selector($node_type); |
| 22 | $form = array_merge($form,$addform); |
| 23 | } else { |
| 24 | |
| 25 | //if this node type is taggable by 1 or more tagnode types, display a link to create new tagnode |
| 26 | //$associated_tagnode_types = array(); |
| 27 | $associated_tagnode_types =(array)_get_associated_tagnode_types($node_type); |
| 28 | |
| 29 | if ($associated_tagnode_types) { |
| 30 | $catstr = t("Select from categories, or")."<br>"; |
| 31 | foreach ($associated_tagnode_types as $associated_tagnode_type) { |
| 32 | $catstr .= " ".l(t("create new ").node_get_name($associated_tagnode_type),"node/add/$associated_tagnode_type"); |
| 33 | }//LOOP back to next link |
| 34 | $catstr .= "<br><br>"; |
| 35 | $form["categories"]["link_label"] = array("#weight"=>-1, "#value" => $catstr); |
| 36 | }//END if ($associated_tagnode_types) |
| 37 | |
| 38 | //check to see if this is a tagnode |
| 39 | $vid = (int)_get_tagnode_vid($node_type); |
| 40 | //watchdog("content","Tagnode form pre: vid = $vid"); |
| 41 | if ($vid && $vid > 0) { |
| 42 | //this is a tagnode. add appropriate form elements |
| 43 | //_utility_tagnode_debug("Tagnode =",$node); |
| 44 | |
| 45 | //add orig title as hidden form field if not already added |
| 46 | //ALWAYS ADD if (! isset($form["tagnode_old_title"])) { |
| 47 | //_utility_tagnode_debug("adding tagnode_old_title...","$node->title"); |
| 48 | $form["tagnode_old_title"] = array("#type"=>"hidden", "#value"=>$node->title); |
| 49 | // } |
| 50 | //_utility_tagnode_debug("Tagnode Form",$form); |
| 51 | } |
| 52 | |
| 53 | }//END if node settings form...else |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | /** |
| 58 | * hook_menu implementation |
| 59 | */ |
| 60 | function tagnode_menu($may_cache) { |
| 61 | $items = array(); |
| 62 | if ($may_cache) { |
| 63 | $items[] = array('path' => 'admin/settings/tagnode', |
| 64 | 'title' => t('tagnode maintenance'), |
| 65 | 'callback' => '_maintain_tagnodes', |
| 66 | 'access' => user_access('administer tagnodes'), |
| 67 | 'type' => MENU_NORMAL_ITEM); |
| 68 | $items[] = array('path' => 'tagnode/help', |
| 69 | 'title' => t('tagnode help'), |
| 70 | 'callback' => 'tagnode_help', |
| 71 | 'access' => user_access('access content'), |
| 72 | 'type' => MENU_CALLBACK); |
| 73 | $items[] = array('path' => 'tagnode', |
| 74 | 'title' => t('all matches'), |
| 75 | 'callback' => '_tagnode_taggees_page', |
| 76 | 'access' => user_access('access content'), |
| 77 | 'type' => MENU_CALLBACK); |
| 78 | $items[] = array('path' => 'tagnode/node/confirm', |
| 79 | 'title' => t('Confirm Tagnode Fix/Delete'), |
| 80 | 'callback' => 'form_orphan_tagnode_node_confirm', |
| 81 | 'access' => user_access('administer tagnodes'), |
| 82 | 'type' => MENU_CALLBACK); |
| 83 | $items[] = array('path' => 'tagnode/node/commit', |
| 84 | 'title' => t('Tagnodes Fixed/Deleted'), |
| 85 | 'callback' => 'form_orphan_tagnode_node_commit', |
| 86 | 'access' => user_access('administer tagnodes'), |
| 87 | 'type' => MENU_CALLBACK); |
| 88 | $items[] = array('path' => 'tagnode/term/confirm', |
| 89 | 'title' => t('Confirm Tagnode Term Delete'), |
| 90 | 'callback' => 'form_orphan_tagnode_term_confirm', |
| 91 | 'access' => user_access('administer tagnodes'), |
| 92 | 'type' => MENU_CALLBACK); |
| 93 | $items[] = array('path' => 'tagnode/term/commit', |
| 94 | 'title' => t('Tagnodes Terms Fixed/Deleted'), |
| 95 | 'callback' => 'form_orphan_tagnode_term_commit', |
| 96 | 'access' => user_access('administer tagnodes'), |
| 97 | 'type' => MENU_CALLBACK); |
| 98 | } else { |
| 99 | theme_add_style(drupal_get_path('module', 'tagnode') .'/tagnode.css'); |
| 100 | } |
| 101 | return $items; |
| 102 | } |
| 103 | |
| 104 | /** |
| 105 | * hook_perm implementation |
| 106 | */ |
| 107 | function tagnode_perm() { |
| 108 | return array('administer tagnodes'); |
| 109 | } |
| 110 | |
| 111 | /** |
| 112 | * hook_help implementation |
| 113 | */ |
| 114 | function tagnode_help($section) { |
| 115 | |
| 116 | switch ($section) { |
| 117 | case 'tagnode/help': |
| 118 | case 'admin/help#tagnode': |
| 119 | return t("This module permits node-to-node associations, using Drupal's taxonomy system. Administrators define 1 or more node types as being "). |
| 120 | "<b>".t("tagnode")."</b> ". t("types. Tagnodes can be tagged to nodes of other types. When a "). |
| 121 | "<b>".t("taggee")."</b> ". |
| 122 | t(" (i.e., a node that is tagged by a tagnode) is rendered, a link is also rendered to the tagnode(s) tagged to it. "). |
| 123 | "<br><br>". |
| 124 | t("Tagnodes facilitate 1-to-many or many-to-many relationships. For example, every event has 1 (or more) location; every music CD has 1 (or more) artist. "). |
| 125 | "<br><br>". |
| 126 | t("More example uses of this module include:"). |
| 127 | "<table><th>".t("Taggee")."</th><th>".t("Tagnode(s)")."</th><tr><td>". |
| 128 | t("event")."</td><td>".t("location, sponsor")."</td></tr><tr><td>". |
| 129 | t("music CD")."</td><td>".t("artist, label")."</td></tr><tr><td>".t("meeting")."</td><td>". |
| 130 | t("organizer, chapter")."</td></tr><tr><td>".t("sport game")."</td><td>".t("field"). |
| 131 | "</td></tr></table><br><br>". |
| 132 | t("Tagnodes are paired with an identically named term from a particular vocabulary. That is, a tagnode = a node of a given type + an identically named term from a given vocabulary. The module uses the node title & term name as the means of linking the 2. "). |
| 133 | "<br><br>". |
| 134 | t("How to create a tagnode relationship:")."<br><ol><li>". |
| 135 | t("Create or identify the node types you need. You can use nodes of any type as the tagnode or as the taggee, but most commonly these nodes are new flexinode types. For example, create a flexinode type called 'event' as the taggee, and create a flexinode type called 'place' to be the tagnode."). |
| 136 | "</li><li>". |
| 137 | t("Create a new vocabulary for tagnode (go to ")."<b>". |
| 138 | t("administer -> categories -> add vocabulary")."</b>". |
| 139 | t("). You can (but do not need to) give it the same name as the tagnode's node type. Check the box(es) of the node types to which the tagnode should be taggable. If you wish that every taggee MUST be tagged with the tagnode, then check the box 'Required'. If you wish that more than 1 tagnode of this type can be tagged to a given node (e.g. 2 or more artists can be credited to a music CD), then check the 'Multiple select' checkbox. In our example, create a new vocabulary named 'place', and check the box next to 'event' node type."). |
| 140 | "</li><li>". |
| 141 | t("Having laid the groundwork, tell the module to link the tagnode's node type and vocabulary. Go to ". |
| 142 | "<b>". |
| 143 | t("administer -> content -> configure -> content types")."</b>". |
| 144 | t(", and click the node type you wish to convert into a tagnode (in our example, click 'place'.) Scroll to near the bottom of the form and find the 'Tagnode' configuration option. In the dropdown menu, select the vocabulary which defines the tagnode (in our example, select 'place'). Submit the form."). |
| 145 | "</li></ol><br>". |
| 146 | t("Once a tagnode is defined, users associate a taggee with a tagnode by selecting the tagnode's name in the dropdown select box in the taggee's form."). |
| 147 | "<br><br>". |
| 148 | t("The module does the following actions:"). |
| 149 | "<ul><li>". |
| 150 | t("When a new tagnode is created, it creates a term (in the tagnode-defining vocabulary) with the identical name."). |
| 151 | "</li><li>". |
| 152 | t("When a tagnode's title is updated, the module updates the corresponding term."). |
| 153 | "</li><li>".t("When a tagnode is deleted, it deletes the term.")."</li><li>". |
| 154 | t("When a taggee is viewed, the tagnode(s) which have been tagged to it are also viewed. A link to the tagnode is displayed as well as the teaser or body of the tagnode."). |
| 155 | "</li><li>". |
| 156 | t("When a taggee's form is rendered, a link is presented to create a new tagnode for each tagnode type it is categorized against."). |
| 157 | "<li>".t("When a tagnode is viewed as a teaser, a link is displayed to each of the node types to which it is taggable."). |
| 158 | "</li><li>". |
| 159 | t("When a tagnode is viewed as a page, a list is shown for each node type, of the most recent n nodes to which this node is tagged."). |
| 160 | "</ul><br>". |
| 161 | t("At the ")."<b>".t("admin -> settings -> tagnode maintenance")."</b>". |
| 162 | t(" page, you can find and fix tagnode-defining nodes and terms which are 'orphaned'. Orphaned nodes and terms can arise when nodes or terms are imported into the database, for example."). |
| 163 | "<br><br>". |
| 164 | t("The module uses the hook_nodeapi() hook to perform its actions. Thus, it can be applied to nodes of any type. It uses no new tables. Since it uses the node title and the term name as a means to link tagnode-defining nodes to the terms, very little data is inserted into the existing tables. The names of tagnode-defining terms should not be changed in the "). |
| 165 | "<b>". |
| 166 | t("administer -> categories")."</b>"). |
| 167 | t(" section."). |
| 168 | "<br><br>".t("If you use the node_import module (or other method) to import tagnodes, be sure to go to "). |
| 169 | "<b>".t("admin -> settings -> tagnode maintenance")."</b>".t(" to add the corresponding terms for the tagnodes you have imported."). |
| 170 | "<br><br>".t("If you wish to have node types properly display as plural (as in 'see all stories' instead of 'see all story'), you might need to add your own implementation of the theme_type_name_display_tagnode() function, in your site's theme. The tagnode module contains a default implementation which properly pluraziles some node types."); |
| 171 | case 'admin/modules#description': |
| 172 | return t('Enables node-to-node associations using the taxonomy system.'); |
| 173 | case 'admin/settings/tagnode': |
| 174 | return t("This page permits the repair or removal of tagnode-defining nodes and terms which are 'orphaned'. " . |
| 175 | "<br><br>Orphaned nodes are tagnode-defining nodes which lack an identically-named term in the" . |
| 176 | " corresponding tagnode-defining vocabulary. Orphaned terms are tagnode-defining terms which" . |
| 177 | "lack an identically-named node of the corresponding node type."). |
| 178 | "<br><br>Orphaned nodes and terms can arise from an administrator modifying a category's " . |
| 179 | "terms in the <b>administer -> categories</b> area. Orphaned nodes also might arise when nodes are " . |
| 180 | "created by an outside mechanism such a node importing module." . |
| 181 | "<br><br>See " . |
| 182 | l(t("the tagnode overview documentation"),"admin/help/tagnode")." for more info on the " . |
| 183 | "tagnode module."; |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | /** |
| 188 | * hook_nodeapi implementation |
| 189 | * |
| 190 | * @ingroup event_nodeapi |
| 191 | */ |
| 192 | function tagnode_nodeapi(&$node, $op, $teaser, $page) { |
| 193 | switch ($op) { |
| 194 | |
| 195 | case "delete": |
| 196 | |
| 197 | //if not tagnode then break |
| 198 | $vid = (int)_get_tagnode_vid($node->type); |
| 199 | if (! $vid || $vid==0) break; |
| 200 | |
| 201 | $oldtitle = $node->title; |
| 202 | |
| 203 | //get the term's tid' |
| 204 | $result = db_query("select tid from {term_data} where vid = %d and name = '%s' ",$vid, $oldtitle); |
| 205 | $oldterm = db_fetch_object($result); |
| 206 | $tid = $oldterm->tid; |
| 207 | |
| 208 | if ($tid) { |
| 209 | //delete the term |
| 210 | watchdog("content","Tagnode deleting term ".$tid); |
| 211 | $status = taxonomy_del_term($tid); |
| 212 | } |
| 213 | break; |
| 214 | |
| 215 | case "insert": |
| 216 | //_utility_tagnode_debug("node",$node); |
| 217 | //if not tagnode then break |
| 218 | $vid = (int)_get_tagnode_vid($node->type); |
| 219 | if (! $vid || $vid==0) break; |
| 220 | |
| 221 | //if this term is being created by tagnode_taxonomy (when user creates a taxonomy term) then break |
| 222 | if ($node->tagnode_creating_node) break; |
| 223 | |
| 224 | $newname = trim($_POST["edit"]["title"]); |
| 225 | |
| 226 | //if a teaser is set, add this to the term's description. |
| 227 | //otherwise set the term's description = the term's name |
| 228 | $stripteaser = trim(strip_tags($node->teaser)); |
| 229 | if ($stripteaser && strlen($stripteaser)>0) { |
| 230 | $newdescription = $stripteaser; |
| 231 | } else { |
| 232 | $newdescription = $newname; |
| 233 | } |
| 234 | //if identical term already exists for this vocab then break |
| 235 | if (_get_tagnode_term($vid,$newname)) break; |
| 236 | |
| 237 | //insert the new term |
| 238 | $newterm = array(); |
| 239 | $newterm["name"] = $newname; |
| 240 | $newterm["description"] = $newdescription; |
| 241 | $newterm["vid"] = $vid; |
| 242 | $newterm["weight"] = 0; |
| 243 | $newterm["tagnode"] = true; |
| 244 | watchdog("content","Inserting term "._utility_tagnode_array_to_string($newterm)); |
| 245 | $status = taxonomy_save_term($newterm); |
| 246 | |
| 247 | break; |
| 248 | |
| 249 | case "load": |
| 250 | |
| 251 | $vid = (int)_get_tagnode_vid($node->type); |
| 252 | if ($vid && $vid > 0) { |
| 253 | //this is a tagnode. Add vid, tid, taggable_types to the node |
| 254 | $term = _get_tagnode_term($vid,$node->title); |
| 255 | $node->tagnode->vid = $vid; |
| 256 | $node->tagnode->tid = $term->tid; |
| 257 | |
| 258 | //get array of node types which are taggable by this tagnode type (if any) |
| 259 | $node->tagnode->taggable_types = _get_tagnode_taggee_types($vid); |
| 260 | //_utility_tagnode_debug("Tagnode Node",$node); |
| 261 | } |
| 262 | |
| 263 | $taggable_by_types = _get_associated_tagnode_types($node->type); |
| 264 | if ($taggable_by_types) { |
| 265 | //this is a taggee. Add the types to which it could be tagged |
| 266 | //and an array of nodes to which it is tagged |
| 267 | $node->tagnode->taggable_by=$taggable_by_types; |
| 268 | $tagged_by_nodes = _get_associated_tagnodes($node->nid); |
| 269 | if ($tagged_by_nodes) $node->tagnode->tagged_by = $tagged_by_nodes; |
| 270 | } |
| 271 | |
| 272 | break; |
| 273 | |
| 274 | case "update": |
| 275 | //_utility_tagnode_debug("node",$node); |
| 276 | //if not tagnode then break |
| 277 | $vid = (int)_get_tagnode_vid($node->type); |
| 278 | if (! $vid || $vid==0) break; |
| 279 | //_utility_tagnode_debug("POST VALUES=",$_POST); |
| 280 | |
| 281 | $oldtitle = $_POST["edit"]["tagnode_old_title"]; |
| 282 | //$newtitle = trim($_POST["edit"]["title"]); |
| 283 | $newtitle = $node->title; |
| 284 | |
| 285 | //if a teaser is set, add this to the term's description. |
| 286 | //otherwise set the term's description = the term's name |
| 287 | $stripteaser = trim(strip_tags($node->teaser)); |
| 288 | if ($stripteaser && strlen($stripteaser)>0) { |
| 289 | $newdescription = $stripteaser; |
| 290 | } else { |
| 291 | $newdescription = $newtitle; |
| 292 | } |
| 293 | |
| 294 | //OLD: if the node's title is unchanged, no need to alter anything |
| 295 | //NEW:[for Glossary.module compatibility] always update the term in case |
| 296 | //the teaser has changed |
| 297 | //if (strcmp($newtitle ,$oldtitle)==0) break; |
| 298 | |
| 299 | //get the term's tid |
| 300 | $result = db_query("select tid from {term_data} where vid = %d and name = '%s'", $vid, $oldtitle); |
| 301 | $oldterm = db_fetch_object($result); |
| 302 | $tid = $oldterm->tid; |
| 303 | |
| 304 | //update w/ the new term |
| 305 | $newterm = array(); |
| 306 | $newterm["tid"] = $tid; |
| 307 | $newterm["name"] = $newtitle; |
| 308 | $newterm["description"] = $newdescription; |
| 309 | watchdog("content","Saving term " . _utility_tagnode_array_to_string($newterm)); |
| 310 | $status = taxonomy_save_term($newterm); |
| 311 | |
| 312 | break; |
| 313 | |
| 314 | case "validate": |
| 315 | |
| 316 | //if not tagnode then break |
| 317 | $vid = (int)_get_tagnode_vid($node->type); |
| 318 | if (! $vid || $vid==0) break; |
| 319 | //this is a tagnode- validate the form |
| 320 | |
| 321 | //if not yet submitted then break |
| 322 | if (!isset($node->title)) break; |
| 323 | |
| 324 | //first trim spaces off the ends |
| 325 | $node->title = trim($node->title); |
| 326 | |
| 327 | $message = "";//the error message |
| 328 | |
| 329 | if ($node->nid) {//this node already exists- i.e. we are updating. |
| 330 | //ensure that if a node of this type exists w/ identical name, it should have current nid |
| 331 | $identicalnames = db_fetch_object(db_query("select n.nid from {node} n where nid != '%d' and n.type='%s' and n.title = '%s'", $node->nid, $node->type, $node->title)); |
| 332 | //$identicalnames = db_fetch_object(db_query(db_rewrite_sql("select nid from {node} where nid != %d and lower(title) = '%s'"), $node->nid, drupal_strtolower($node->title))); |
| 333 | |
| 334 | } else {//this node does not exist- i.e. we are inserting |
| 335 | //ensure there is no node of this type w/ identical name |
| 336 | $identicalnames = db_fetch_object(db_query("select n.nid from {node} n where n.type='%s' and n.title = '%s'", $node->type, $node->title)); |
| 337 | } |
| 338 | |
| 339 | if ($identicalnames) $message .= "'$node->title' " . t("already exists in the database. ").l(t("Click here to see it."),"node/{$identicalnames->nid}"); |
| 340 | |
| 341 | //if an error message has been defined, set the error in the form |
| 342 | if (drupal_strlen($message)) { |
| 343 | form_set_error("node-form", $message); |
| 344 | } else { |
| 345 | //let them pass |
| 346 | } |
| 347 | break; |
| 348 | |
| 349 | case "view": |
| 350 | $addhtml = ""; |
| 351 | //Taggees: show tagnode info |
| 352 | if ($node->tagnode->tagged_by) $addhtml .= theme("tagnode_list",(array)$node->tagnode->tagged_by,$teaser); |
| 353 | |
| 354 | //Tagnodes: show nodes to which they are tagged |
| 355 | if ($node->tagnode->taggable_types) { |
| 356 | $addhtml .= theme("tagnode_view_taggees",$node,$teaser,5); |
| 357 | } |
| 358 | //append to the proper field |
| 359 | $appendtofield = "body";//default to body |
| 360 | if ($teaser) $appendtofield = "teaser"; |
| 361 | $node->$appendtofield .= $addhtml; |
| 362 | |
| 363 | $node->tagnode_append = $addhtml; |
| 364 | break; |
| 365 | }//end switch |
| 366 | } |
| 367 | |
| 368 | function tagnode_taxonomy($op, $type, $term=null) { |
| 369 | |
| 370 | //if this is a term and if it is NOT being inserted by tagnode (instead it is being inserted e.g. by freetagging), then create the corresponding node |
| 371 | if ($type!="term" || isset($term["tagnode"])) return; |
| 372 | switch ($op) { |
| 373 | case "insert": |
| 374 | $tagnode_type = _get_tagnode_types($term["vid"]); |
| 375 | if (!$tagnode_type) break; |
| 376 | $tagnode_title = $term["name"]; |
| 377 | watchdog("content", "Inserting Tagnode Node for term "._utility_tagnode_array_to_string($term)); |
| 378 | $tagnode->type = $tagnode_type; |
| 379 | $tagnode->title = $term["name"]; |
| 380 | $tagnode->tagnode_creating_node = 1; |
| 381 | $tagnode->created = time(); |
| 382 | if ($user->uid) { $tagnode->uid = $user->uid; } else {$tagnode->uid = 1;} |
| 383 | |
| 384 | if (! node_access("create", $tagnode)) { |
| 385 | watchdog("error", "insufficient rights to create tagnode '$tagnode->title' of type $tagnode->type"); |
| 386 | } else { |
| 387 | node_save($tagnode); |
| 388 | watchdog("content","successfully created tagnode node '$tagnode->title'"); |
| 389 | } |
| 390 | break; |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | |
| 395 | /** |
| 396 | * Shows a list of taggees of a single type, including a header containing the node type, |
| 397 | * This list appears on a page view of a tagnode node. Hardcoded to show most recent 5 posts |
| 398 | * If available, uses theme_type_name_display_tagnode, |
| 399 | * which renders the plural form of the node type name. |
| 400 | * (This should probably be accomplished with translation/internationalization |
| 401 | * functinality instead.) |
| 402 | * |
| 403 | * @param $tagnode the tagnode whose taggees we are displaying |
| 404 | * @param $tagged_to_type the type of node we are listing |
| 405 | * @param $number_to_show the number to show. Default=5 |
| 406 | */ |
| 407 | function theme_list_tagnode_taggees_by_type($tagnode,$tagged_to_type,$number_to_show=5) { |
| 408 | //4.6 $tagnodetypedisplay = node_invoke($tagged_to_type,"node_name"); |
| 409 | $tagnodetypedisplay = node_get_name($tagged_to_type); |
| 410 | $tagnodetypedisplay = theme("type_name_display_tagnode",$tagnodetypedisplay,true); |
| 411 | $headerhtml = "<h3>$tagnodetypedisplay</h3>"; |
| 412 | $listhtml=""; |
| 413 | $linkhtml=""; |
| 414 | |
| 415 | |
| 416 | //get query of items to show |
| 417 | $sql = "SELECT n.nid " . |
| 418 | " FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid " . |
| 419 | " WHERE tn.tid = %d AND n.status = 1 AND n.type = '%s' " . |
| 420 | " ORDER BY %s"; |
| 421 | $result=db_query_range($sql,$tagnode->tagnode->tid,$tagged_to_type,"n.sticky DESC, n.created DESC",0,$number_to_show); |
| 422 | |
| 423 | while($taggee_nid = db_fetch_object($result)) { |
| 424 | //4.6 $taggee = node_load((array)$taggee_nid); |
| 425 | $taggeeA = (array)$taggee_nid; |
| 426 | $taggee = node_load($taggeeA["nid"]); |
| 427 | $listhtml .= theme("tagnode_taggee_item", $taggee); |
| 428 | } |
| 429 | if (!$listhtml) return $listhtml; |
| 430 | |
| 431 | $linkhtml = "<br>" . l(t("view all ".$tagnodetypedisplay),"tagnode/{$tagged_to_type}/{$tagnode->tagnode->tid}"); |
| 432 | |
| 433 | return $headerhtml . $listhtml . $linkhtml; |
| 434 | } |
| 435 | |
| 436 | /** |
| 437 | * Themes each taggee list item. Called by theme_list_tagnode_taggees_by_type, when |
| 438 | * the latter is generating a summary list of taggees. This appears on the page view |
| 439 | * of a tagnode node. |
| 440 | * |
| 441 | * You might wish to override this function in your custom theme if you have specialized |
| 442 | * node types (currently, events and images). Please send me a patch or the line of code |
| 443 | * to add if you identify other node types which should be rendered here. |
| 444 | |
| 445 | * @param $taggee the taggee node to render |
| 446 | * |
| 447 | */ |
| 448 | function theme_tagnode_taggee_item($taggee) { |
| 449 | $itemhtml = ""; |
| 450 | |
| 451 | $itemhtml = l($taggee->title,"node/$taggee->nid") . "<br>"; |
| 452 | |
| 453 | //for events: show start time |
| 454 | if ($taggee->start_format) $itemhtml.= $taggee->start_format . "<br>"; |
| 455 | |
| 456 | //if image: show image |
| 457 | if ($taggee->images) $itemhtml.= l(image_display($taggee, 'thumbnail'), 'node/'.$taggee->nid, array(), NULL, NULL, FALSE, TRUE); |
| 458 | |
| 459 | return $itemhtml; |
| 460 | } |
| 461 | /** |
| 462 | * This is called when viewing a tagnode. |
| 463 | * Renders info regarding the taggees to which it is tagged. |
| 464 | * I suspect you would not generally need to modify this theme for your custom theme. |
| 465 | * This theme calls theme_tagnode_view_taggees_teaser if we are viewing in teaser mode, |
| 466 | * otherwise it calls theme_list_tagnode_taggees_by_type. |
| 467 | * |
| 468 | * @param $tagnode the tagnode being viewed |
| 469 | * @param $teaser if true, we are viewing the teaser form of the node |
| 470 | * @param $number_to_show the number of taggees to list for each type of taggee |
| 471 | */ |
| 472 | function theme_tagnode_view_taggees($tagnode,$teaser,$number_to_show) { |
| 473 | |
| 474 | $returnhtml = ""; |
| 475 | if ($teaser) return theme("tagnode_view_taggees_teaser",$tagnode->tagnode->vid,$tagnode->tagnode->tid,$tagnode->tagnode->taggable_types); |
| 476 | foreach($tagnode->tagnode->taggable_types as $taggable_type) { |
| 477 | $returnhtml.=theme("list_tagnode_taggees_by_type",$tagnode,$taggable_type,$number_to_show); |
| 478 | } |
| 479 | return $returnhtml; |
| 480 | } |
| 481 | |
| 482 | /** |
| 483 | * This is called when viewing a taggee node. Shows all tagnodes which tag this taggee node. |
| 484 | * These appear as fields under the taggee node's regular fields, as in |
| 485 | * Artist: The Beatles |
| 486 | * Label: Apple Records |
| 487 | * with "The Beatles" and "Apple Records" being links to the |
| 488 | * respective tagnodes "The Beatles" and "Apple Records" |
| 489 | * |
| 490 | * Calls theme_type_name_display_tagnode to change the node type name for your purposes |
| 491 | * (e.g. I use it to pluralize the node type name) |
| 492 | * Calls theme_tagnode_tag to render each tag |
| 493 | * |
| 494 | * @param $tagnodes the array of tagnodes which are tagged to this node |
| 495 | * (from $node->tagnode->tagged_by) |
| 496 | * @param $teaser true if we are viewing this node in teaser mode |
| 497 | */ |
| 498 | function theme_tagnode_list($tagnodes,$teaser) { |
| 499 | $returnhtml = ""; |
| 500 | foreach($tagnodes as $tagnode) { |
| 501 | //4.6 $tagnodetype = node_invoke($tagnode->type,"node_name"); |
| 502 | $tagnodetype = node_get_name($tagnode->type); |
| 503 | $tagnodetypedisplay = theme("type_name_display_tagnode",$tagnodetype,false,true); |
| 504 | $returnhtml.=theme("tagnode_tag",$tagnodetypedisplay,$tagnode,$teaser); |
| 505 | } |
| 506 | return $returnhtml; |
| 507 | } |
| 508 | |
| 509 | /** |
| 510 | * Displays a single element of a tagnode as in |
| 511 | * Artist: The Beatles |
| 512 | * |
| 513 | * This is called from theme_tagnode_list() when the latter is rendering a taggee node's tagnodes |
| 514 | * When displaying the taggee's teaser, display only 'node type: node title' with a link to the tagnode. |
| 515 | * When displaying in non-teaser mode, display the tagnode's title followed by its teaser, |
| 516 | * themed by theme_box. |
| 517 | */ |
| 518 | function theme_tagnode_tag($label,$tagnode,$teaser=false) { |
| 519 | $returnhtml=""; |
| 520 | if ($teaser) { |
| 521 | $returnhtml = "<div class='tagnode-tag'><div class='{$label}-label'><label>{$label}: </label>".l($tagnode->title,"node/$tagnode->nid")."</div></div>"; |
| 522 | } else { |
| 523 | $returnhtml = theme("box",$label, l($tagnode->title,"node/$tagnode->nid") . $tagnode->teaser); |
| 524 | } |
| 525 | return $returnhtml; |
| 526 | } |
| 527 | |
| 528 | /** |
| 529 | * Called when viewing a tagnode in teaser mode; displays "Find:" links, which point to |
| 530 | * a page where all taggees of the clicked type are displayed. |
| 531 | * |
| 532 | * @param $vid the tagnode-defining vocabulary's vid of the taggees to retrieve |
| 533 | * @param $tid the tagnode-defining term's tid of the taggees to retrieve |
| 534 | */ |
| 535 | function theme_tagnode_view_taggees_teaser($vid,$tid,$taggable_types) { |
| 536 | $returnhtml = "<div class='tagnode-tag'><div class='find-label'><label>".t("Find").": </label>"; |
| 537 | foreach ($taggable_types as $taggable_type) { |
| 538 | $returnhtml.=theme("tagnode_teaser_item",$tid,$taggable_type)." "; |
| 539 | } |
| 540 | $returnhtml .= "</div></div>"; |
| 541 | return $returnhtml; |
| 542 | } |
| 543 | |
| 544 | /** |
| 545 | * Called by theme_tagnode_view_taggees_teaser() for each link to be rendered |
| 546 | * after the "Find:" label. Uses theme_type_name_display_tagnode() to convert |
| 547 | * each node type name into a plural form, if desired |
| 548 | */ |
| 549 | function theme_tagnode_teaser_item($tid,$taggable_type) { |
| 550 | $returnhtml = ""; |
| 551 | //4.6 $typedisplay = node_invoke($taggable_type,"node_name"); |
| 552 | $typedisplay = node_get_name($taggable_type); |
| 553 | $typedisplay = theme("type_name_display_tagnode",$typedisplay,true); |
| 554 | //$querystring = "nid=$nid&type=".urlencode($taggable_type); |
| 555 | $returnhtml.=l($typedisplay,"tagnode/{$taggable_type}/{$tid}"); |
| 556 | return $returnhtml; |
| 557 | } |
| 558 | |
| 559 | /** |
| 560 | * Themes a node type display name into plural and/or capitalized format. Also can capitalize. |
| 561 | * |
| 562 | * This funcctionality should probably be replaced with Drupal's translation |
| 563 | * functionality. |
| 564 | * |
| 565 | * @param $display_name the displayable name of the node type, as in "event" (not "flexinode-1") |
| 566 | * @param $pluralize if true will return plural form of the name |
| 567 | * @param $capitalize if true will capitalize all words in the name using PHP function ucwords() |
| 568 | */ |
| 569 | function theme_type_name_display_tagnode($display_name, $pluralize = false, $capitalize = false) { |
| 570 | $return_name = $display_name; |
| 571 | switch ($display_name) { |
| 572 | case "event": |
| 573 | if ($pluralize) { |
| 574 | $return_name = "events"; |
| 575 | } |
| 576 | break; |
| 577 | case "place": |
| 578 | if ($pluralize) { |
| 579 | $return_name = "places"; |
| 580 | } |
| 581 | break; |
| 582 | case "group": |
| 583 | if ($pluralize) { |
| 584 | $return_name = "groups"; |
| 585 | } |
| 586 | break; |
| 587 | case "forum topic": |
| 588 | if ($pluralize) { |
| 589 | $return_name = "forum topics"; |
| 590 | } |
| 591 | break; |
| 592 | case "image": |
| 593 | if ($pluralize) { |
| 594 | $return_name = "images"; |
| 595 | } |
| 596 | break; |
| 597 | case "story": |
| 598 | if ($pluralize) { |
| 599 | $return_name = "stories"; |
| 600 | } |
| 601 | break; |
| 602 | case "poll": |
| 603 | if ($pluralize) { |
| 604 | $return_name = "polls"; |
| 605 | } |
| 606 | break; |
| 607 | case "page": |
| 608 | if ($pluralize) { |
| 609 | $return_name = "pages"; |
| 610 | } |
| 611 | break; |
| 612 | case "personal blog entries": |
| 613 | if ($pluralize) { |
| 614 | $return_name = "personal blog entries"; |
| 615 | } |
| 616 | break; |
| 617 | case "survey": |
| 618 | if ($pluralize) { |
| 619 | $return_name = "surveys"; |
| 620 | } |
| 621 | break; |
| 622 | case "forum topic": |
| 623 | if ($pluralize) { |
| 624 | $return_name = "forum topics"; |
| 625 | } |
| 626 | break; |
| 627 | } |
| 628 | if ($capitalize) $return_name = ucwords($return_name); |
| 629 | return $return_name; |
| 630 | } |
| 631 | |
| 632 | /** |
| 633 | * Retrieves an array of tagnode types, keyed by the corresponding vocab id. |
| 634 | * Stores this as a variable, "tagnode_types". |
| 635 | * Retrieves an array of tagnode vocabs ordered by their weight (secondarily by their alphabetic order). |
| 636 | * Stores this as a variable, "tagnode_vids". |
| 637 | * and sets the flag to true signalling that the cached value may be used. This flag is set to 0 (false) |
| 638 | * each time the node settings form is submitted. |
| 639 | */ |
| 640 | function _cache_tagnode_info() { |
| 641 | variable_set("tagnode_unchanged",1); |
| 642 | $tagnode_types = array(); |
| 643 | $result = db_query("select * from {variable} where name like '%%%s%%'", _get_tagnode_varname()); |
| 644 | |
| 645 | while ($tagnode = db_fetch_object($result)) { |
| 646 | $thisval = unserialize($tagnode->value); |
| 647 | if ($thisval != "0") { |
| 648 | $tagnode_types[$thisval] = str_replace(_get_tagnode_varname(),"",$tagnode->name); |
| 649 | } |
| 650 | } |
| 651 | |
| 652 | //Only attempt to cache if there are any tagnodes |
| 653 | if ($tagnode_types && is_array($tagnode_types) && count($tagnode_types)>0) { |
| 654 | variable_set("tagnode_types",$tagnode_types); |
| 655 | |
| 656 | $tagnode_vids = array_flip($tagnode_types); |
| 657 | variable_set("tagnode_vids",$tagnode_vids); |
| 658 | |
| 659 | $tagnode_vid_list = _utility_tagnode_array_to_qualified_string($tagnode_vids,",",""); |
| 660 | |
| 661 | $tagnode_vids_ordered = array(); |
| 662 | if (drupal_strlen($tagnode_vid_list)>0) { |
| 663 | $result = db_query("select * from {vocabulary} where vid in ($tagnode_vid_list) order by weight,name"); |
| 664 | while ($vocab = db_fetch_object($result)) { |
| 665 | $tagnode_vids_ordered[] = $vocab->vid; |
| 666 | } |
| 667 | } |
| 668 | variable_set("tagnode_vids_ordered",$tagnode_vids_ordered); |
| 669 | }//...otherwise set the cache with a null array and clear all tagnode cache variables |
| 670 | else { |
| 671 | $null_array = array(); |
| 672 | variable_set("tagnode_types",$null_array); |
| 673 | variable_set("tagnode_vids",$null_array); |
| 674 | variable_set("tagnode_vids_ordered",$null_array); |
| 675 | } |
| 676 | } |
| 677 | |
| 678 | /** |
| 679 | * For a given taggee type, returns an array of tagnodes which can be tagged to it, |
| 680 | * in prioritized order (i.e. by weight of the tagnodes' vocabularies). |
| 681 | */ |
| 682 | function _get_associated_tagnode_types($nodetype) { |
| 683 | $tagnode_nodetypes = array(); |
| 684 | $all_tagnode_vocabs = (array)_get_tagnode_vids(); |
| 685 | if ($all_tagnode_vocabs) { |
| 686 | $vocabs_for_this_node_type = array(); |
| 687 | $vocabs_for_this_node_type = taxonomy_get_vocabularies($nodetype); |
| 688 | |
| 689 | foreach($all_tagnode_vocabs as $tagnode_vid) { |
| 690 | if (array_key_exists($tagnode_vid,$vocabs_for_this_node_type)) { |
| 691 | $tagnode_nodetypes[] = _get_tagnode_types($tagnode_vid); |
| 692 | } |
| 693 | } |
| 694 | } |
| 695 | |
| 696 | return $tagnode_nodetypes; |
| 697 | } |
| 698 | |
| 699 | /** |
| 700 | * returns an array containing each tagnode which has been associated w/ this node |
| 701 | */ |
| 702 | function _get_associated_tagnodes($nodeid) { |
| 703 | |
| 704 | //the array to return |
| 705 | $my_tagnodes = array(); |
| 706 | |
| 707 | //get all taxonomy terms associated w/ this node, in weighted order |
| 708 | $associated_terms = taxonomy_node_get_terms($nodeid); |
| 709 | |
| 710 | //if no terms then no tagnodes |
| 711 | if (!$associated_terms) return $my_tagnodes; |
| 712 | |
| 713 | /* loop thru all terms associated w/ this node. If any term defines a tagnode then |
| 714 | * add it to the array of tagnode-defining-terms |
| 715 | */ |
| 716 | |
| 717 | foreach ($associated_terms as $associated_term) { |
| 718 | $tagnode = _get_tagnode_from_termid($associated_term->tid); |
| 719 | if ($tagnode && $tagnode->nid) { |
| 720 | $tagnode->vid = $associated_term->vid; |
| 721 | //if we find a tagnode associated w/ this term and |
| 722 | //if this node is not the current node, |
| 723 | //then add it to the array of associated tagnodes |
| 724 | if ($tagnode->nid != $nodeid) $my_tagnodes[] = $tagnode; |
| 725 | } |
| 726 | } |
| 727 | |
| 728 | //$my_tagnodeids should now contain the tid of each tagnode associated w/ this term |
| 729 | if ($my_tagnodes) { |
| 730 | return $my_tagnodes; |
| 731 | } else { |
| 732 | $my_tagnodes = array(); |
| 733 | return $my_tagnodes; |
| 734 | } |
| 735 | } |
| 736 | |
| 737 | /** |
| 738 | * returns the tagnode which corresponds to the provided tid, or $default |
| 739 | * if none corresponds. |
| 740 | */ |
| 741 | function _get_tagnode_from_termid($termid,$default = FALSE) { |
| 742 | //get the term object |
| 743 | $termobj = taxonomy_get_term($termid); |
| 744 | |
| 745 | //get the vocab id |
| 746 | $vocabid = $termobj->vid; |
| 747 | |
| 748 | //get the tagnode node type for this vocabulary |
| 749 | $nodetype = _get_tagnode_types($vocabid); |
| 750 | |
| 751 | if (! $nodetype) return $default; |
| 752 | |
| 753 | /* |
| 754 | $result = db_query("SELECT nid, type, title, teaser, body FROM {node} WHERE status = 1 AND " . |
| 755 | "type = '%s' AND title = '%s'" ,$nodetype,$termobj->name); |
| 756 | $tagnode = db_fetch_object($result); |
| 757 | |
| 758 | if (db_num_rows($result) < 1) return $default; |
| 759 | */ |
| 760 | $criteria = array( "type" => "$nodetype", "title" => $termobj->name); |
| 761 | $tagnode = node_load($criteria); |
| 762 | if (!$tagnode) return $default; |
| 763 | |
| 764 | $tagnode->tid = $termid; |
| 765 | //_utility_tagnode_debug("Loaded Tagnode",$tagnode); |
| 766 | return $tagnode; |
| 767 | } |
| 768 | |
| 769 | /** |
| 770 | * finds all nodes of the provided type and catagorized against the provided term. |
| 771 | * and returns the result resource. |
| 772 | */ |
| 773 | function _get_tagnode_nodes_by_type_and_term($nodetype,$termid ,$maxrecords = "all", $orderby="n.sticky DESC, n.created DESC") { |
| 774 | $maxrecsnum = (int)$maxrecords; |
| 775 | $sql = "SELECT n.nid " . |
| 776 | " FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid " . |
| 777 | " WHERE tn.tid = %d AND n.status = 1 AND n.type = '%s' " . |
| 778 | " ORDER BY %s"; |
| 779 | |
| 780 | $result = pager_query($sql,variable_get('default_nodes_main', 10),0,null,$termid,$nodetype,$orderby); |
| 781 | //_utility_tagnode_debug("Get nodes of type $nodetype categorized against term $termid; SQL = $sql",$result); |
| 782 | return $result; |
| 783 | } |
| 784 | |
| 785 | /** |
| 786 | * returns an array containing every node type which defines a tagnode. If a $vid is |
| 787 | * passed, retrieves only those node types which are tagnodes by association w/ the provided |
| 788 | * vocab id (vid). This function ensures that the cache of tagnode info is fresh. If so, it retrieves |
| 789 | * this info from the persistent variables. If not, refreshes this cache. |
| 790 | */ |
| 791 | function _get_tagnode_types($vid = null) { |
| 792 | $tagnode_types = array(); |
| 793 | |
| 794 | //ensure cache is fresh |
| 795 | $tagnode_unchanged = variable_get("tagnode_unchanged",false); |
| 796 | if (! $tagnode_unchanged) _cache_tagnode_info(); |
| 797 | |
| 798 | $tagnode_types = variable_get("tagnode_types",false); |
| 799 | |
| 800 | //if tagnode_types is null or false, or if no $vid was passed, return $tagnode_types |
| 801 | if (! $tagnode_types || !$vid) return $tagnode_types; |
| 802 | |
| 803 | //a $vid was passed |
| 804 | if (array_key_exists($vid,$tagnode_types)) { |
| 805 | return $tagnode_types[$vid]; |
| 806 | } else { |
| 807 | return false; |
| 808 | } |
| 809 | } |
| 810 | |
| 811 | /** |
| 812 | * returns all node types categorized by the provided $vid (i.e. tagged by the vid's tagnode) |
| 813 | */ |
| 814 | function _get_tagnode_taggee_types($vid) { |
| 815 | $result = db_query("select type from {vocabulary_node_types} where vid = %d order by type",$vid); |
| 816 | $types = array(); |
| 817 | while ($typeobj = db_fetch_object($result)) { |
| 818 | //$types[] = node_invoke($typeobj->type,"node_name"); |
| 819 | $types[] = $typeobj->type; |
| 820 | } |
| 821 | return $types; |
| 822 | } |
| 823 | |
| 824 | /** |
| 825 | * returns the variable name for the specified noe type |
| 826 | */ |
| 827 | function _get_tagnode_varname($nodetype = "") { |
| 828 | return "tagnode_nodeapi_".$nodetype; |
| 829 | } |
| 830 | |
| 831 | /** |
| 832 | * retrieves the vid which defines a tagnode with the provided node type. |
| 833 | * |
| 834 | * This function ensures that the cache of tagnode info is fresh. If so, it retrieves |
| 835 | * this info from the persistent variables. If not, refreshes this cache. |
| 836 | */ |
| 837 | function _get_tagnode_vid($nodetype = null) { |
| 838 | $tagnode_vids_ordered = array(); |
| 839 | |
| 840 | //ensure cache is fresh |
| 841 | $tagnode_unchanged = variable_get("tagnode_unchanged",false); |
| 842 | |
| 843 | if (! $tagnode_unchanged) { |
| 844 | _cache_tagnode_info(); |
| 845 | } |
| 846 | |
| 847 | $tagnode_vids = variable_get("tagnode_vids",false); |
| 848 | if ($tagnode_vids && array_key_exists($nodetype,$tagnode_vids)) { |
| 849 | return (int)$tagnode_vids[$nodetype]; |
| 850 | } else { |
| 851 | return false; |
| 852 | } |
| 853 | |
| 854 | } |
| 855 | |
| 856 | /** |
| 857 | * Gets an array containing all tagnode vids |
| 858 | */ |
| 859 | function _get_tagnode_vids() { |
| 860 | $tagnode_vids_ordered = array(); |
| 861 | |
| 862 | //ensure cache is fresh |
| 863 | $tagnode_unchanged = variable_get("tagnode_unchanged",false); |
| 864 | |
| 865 | if (! $tagnode_unchanged) { |
| 866 | _cache_tagnode_info(); |
| 867 | } |
| 868 | |
| 869 | $tagnode_vids_ordered = (array)variable_get("tagnode_vids_ordered",null); |
| 870 | return (array)$tagnode_vids_ordered; |
| 871 | } |
| 872 | |
| 873 | /** |
| 874 | * returns true if the term id defines a tagnode |
| 875 | */ |
| 876 | function _is_tagnode_term($termid) { |
| 877 | |
| 878 | //get the array of all tagnode vocab ids |
| 879 | $tagnode_vocabids = (array)_get_tagnode_vids(); |
| 880 | if ($tagnode_vocabids == NULL) return false; |
| 881 | |
| 882 | //get the vocab id of the specified term |
| 883 | $termobj = taxonomy_get_term($termid); |
| 884 | $vocabid = $termobj->vid; |
| 885 | if (in_array($vocabid,$tagnode_vocabids)) { |
| 886 | return true; |
| 887 | } else { |
| 888 | return false; |
| 889 | } |
| 890 | } |
| 891 | |
| 892 | /** |
| 893 | * Housekeeping form: displays orphaned tagnode nodes & terms, and duplicitave |
| 894 | * tagnode node titles or term names. Permits the admin to fix these |
| 895 | * discrepancies |
| 896 | */ |
| 897 | function _maintain_tagnodes() { |
| 898 | // *************** ORPAHNED TAGNODE NODE FIX/DELETE FORM ********************* |
| 899 | $form_node = array(); |
| 900 | $page_html = ""; |
| 901 | $form_node["#action"]= url("tagnode/node/confirm"); |
| 902 | $text_node = "";//the message to display in lieu of form (if any) |
| 903 | //$form_node["header_nodes"] = array("#value" => "<h2>".t("Orphaned Nodes")."</h2>"); |
| 904 | $tagnode_types = _utility_tagnode_array_to_qualified_string((array)_get_tagnode_types()); |
| 905 | $tagnode_type_str = " and 1=0 "; |
| 906 | if (strlen($tagnode_types)>0) $tagnode_type_str = "and n.type in (".$tagnode_types.")"; |
| 907 | $sql = "select n.nid, n.title, n.type from {node} n LEFT JOIN {term_data} t ON n.title = t.name " . |
| 908 | "where n.status=1 $tagnode_type_str and t.name is NULL"; |
| 909 | |
| 910 | //_utility_tagnode_debug("sql = ",$sql); |
| 911 | $result = db_query($sql); |
| 912 | |
| 913 | //watchdog("content","Housekeeping form: SQL=$sql; finds ".db_num_rows($result)." results."); |
| 914 | if (db_num_rows($result)>0) {//more than 0 results? Show table/form to fix or delete orphaned tagnodes |
| 915 | $orphaned_tagnode_nodes=array(); |
| 916 | $orphaned_tagnode_node_titles=array(); |
| 917 | $form_node["description_node"]=array("#value" => t("These are tagnodes which lack a corresponding identically named term, and thus will not tag properly").".<br><br>"); |
| 918 | $form_node["node_table_start"]=array("#value" => "<table><th>".t("Fix?")."</th><th>".t("Orphaned Node")."</th><th>".t("Type")."</th><th>".t("Delete?")."</th>"); |
| 919 | while($orphaned_tagnode = db_fetch_object($result)) { |
| 920 | $itemname = "_".$orphaned_tagnode->nid; |
| 921 | |
| 922 | $form_node["start_row".$itemname]=array("#value" => "<tr><td align='center'>"); |
| 923 | |
| 924 | $orphaned_tagnode_nodes[] = $orphaned_tagnode->nid; |
| 925 | $orphaned_tagnode_node_titles[] = $orphaned_tagnode->title; |
| 926 | //4.6 $form1.= form_checkbox("","orphan_tagnode_node_fix".$itemname,"1",true); |
| 927 | $form_node["orphan_tagnode_node_fix".$itemname] = array( |
| 928 | '#type' => 'checkbox', |
| 929 | '#title' => "", |
| 930 | '#return_value' => "1", |
| 931 | '#default_value' => true, |
| 932 | ); |
| 933 | |
| 934 | $form_node["mid_row1".$itemname]=array( "#value"=>"</td><td>$orphaned_tagnode->title</td><td>"); |
| 935 | //4.6 $form1.= node_invoke($orphaned_tagnode->type, 'node_name'); |
| 936 | $form_node["mid_row2".$itemname]=array("#value"=> node_get_name($orphaned_tagnode->type)."</td><td align='center'>"); |
| 937 | //4.6 $form1.= form_checkbox("","orphan_tagnode_node_delete".$itemname,"1",false); |
| 938 | $form_node["orphan_tagnode_node_delete".$itemname] = array( |
| 939 | '#type' => 'checkbox', |
| 940 | '#title' => "", |
| 941 | '#return_value' => "1", |
| 942 | '#default_value' => false, |
| 943 | ); |
| 944 | |
| 945 | $form_node["end_row".$itemname]=array("#value"=>"</td></tr>"); |
| 946 | //watchdog("content","itemname=$itemname"); |
| 947 | }//LOOP back |
| 948 | $form_node["submit_row"]=array( "#value"=>"<tr><td colspan='4' align='center'>"); |
| 949 | //4.6 $form1.=form_submit(t("submit"),"orphan_tagnode_node_submit"); |
| 950 | $form_node["orphan_tagnode_node_submit"] = array( |
| 951 | '#type' => 'submit', |
| 952 | '#value' => 'submit' |
| 953 | ); |
| 954 | $form_node["end_submit_row"]=array( "#value"=>"</td></tr></table>"); |
| 955 | |
| 956 | //4.6 $form1.=form_hidden("orphaned_tagnode_nodes",_utility_tagnode_array_to_url_string($orphaned_tagnode_nodes)); |
| 957 | $form_node["orphaned_tagnode_nodes"] = array( |
| 958 | '#type' => "hidden", |
| 959 | '#value' => _utility_tagnode_array_to_url_string($orphaned_tagnode_nodes) |
| 960 | ); |
| 961 | |
| 962 | //4.6 $form1.=form_hidden("orphaned_tagnode_node_titles",_utility_tagnode_array_to_url_string($orphaned_tagnode_node_titles)); |
| 963 | $form_node["orphaned_tagnode_node_titles"] = array( |
| 964 | '#type' => "hidden", |
| 965 | '#value' => _utility_tagnode_array_to_url_string($orphaned_tagnode_node_titles) |
| 966 | ); |
| 967 | //watchdog("content","created orphaned_tagnode_node_titles"); |
| 968 | //$page.=form($form1); |
| 969 | //$page.="</table>"; |
| 970 | $form_node["description"]=array( "#value"=> "<br>'<b>".t("Fix")."</b>': ".t("A new term of identical title will be inserted into the proper vocabulary, thus repairing the tagnode.")."<br><b>".t("Delete")."</b>': ".t("The node will be deleted")."<br>".t("Note that neither of these actions will repair or delete any orphaned terms.")); |
| 971 | } else {//ELSE more than 0 results? Show table/form to fix or delete orphaned tagnodes |
| 972 | $text_node .= t("There are no orphaned nodes."); |
| 973 | }//END more than 0 results? Show table/form to fix or delete orphaned tagnodes |
| 974 | |
| 975 | // *************ORPHANED NODE: RENDER OUTPUT**************************** |
| 976 | if (strlen($text_node)===0) $text_node = drupal_get_form("form_orphan_tagnode_node", $form_node); |
| 977 | |
| 978 | $page_html.= theme("box", t("Orphaned Tagnode Nodes"),$text_node); |
| 979 | |
| 980 | // *************ORPHANED TERMS*************************** |
| 981 | // *************** ORPAHNED TAGNODE TERMS DELETE FORM ********************* |
| 982 | $form_term = array(); |
| 983 | $text_term = "";//the message to display in lieu of form (if any) |
| 984 | $form_term["#action"] = "tagnode/term/confirm"; |
| 985 | //$form_term["header_terms"] = array("#value" => "<h2>".t("Orphaned Terms")."</h2>"); |
| 986 | $tagnode_vocabs = _utility_tagnode_array_to_qualified_string((array)_get_tagnode_vids(),",",""); |
| 987 | /* |
| 988 | $sql = "select t.tid, t.name, t.vid from {term_data} t LEFT JOIN {node} n ON t.name = n.title " . |
| 989 | "where t.vid in ($tagnode_vocabs) and n.title is NULL"; |
| 990 | */ |
| 991 | |
| 992 | $tagnode_vocab_str = " 1=0 and "; |
| 993 | if ($tagnode_vocabs) $tagnode_vocab_str = "t.vid in ($tagnode_vocabs) and "; |
| 994 | $sql = "select t.tid, t.name, t.vid from {term_data} t LEFT JOIN {node} n ON t.name = n.title " . |
| 995 | "where $tagnode_vocab_str n.title is NULL"; |
| 996 | |
| 997 | $result = db_query($sql); |
| 998 | //$page_html.= "Queried w/ SQL $sql; found ".db_num_rows($result)." results"; |
| 999 | if (db_num_rows($result)>0) {//more than 0 result? Show table/form to delete orphaned tagnode terms |
| 1000 | $orphaned_tagnode_terms=array(); |
| 1001 | $orphaned_tagnode_term_names=array(); |
| 1002 | $form_term["description_term"]=array("#value" => t("These are tagnode terms which lack a corresponding identically named node, and thus will not tag properly").".<br><br>"); |
| 1003 | $form_term["term_table_start"]=array("#value" => "<table><th>".t("Delete?")."</th><th>".t("Orphaned Term")."</th><th>".t("Vocabulary")."</th>"); |
| 1004 | |
| 1005 | while($orphaned_tagnode_term = db_fetch_object($result)) { |
| 1006 | $itemname = "_".$orphaned_tagnode_term->tid; |
| 1007 | $form_term["term_row_start".$itemname]=array("#value" => "<tr><td align='center'>"); |
| 1008 | $orphaned_tagnode_terms[] = $orphaned_tagnode_term->tid; |
| 1009 | $orphaned_tagnode_term_names[] = $orphaned_tagnode_term->name; |
| 1010 | //4.6 $form3.= form_checkbox("","orphan_tagnode_term_delete".$itemname,"1",true); |
| 1011 | $form_term["orphan_tagnode_term_delete".$itemname] = array( |
| 1012 | '#type' => 'checkbox', |
| 1013 | '#title' => "", |
| 1014 | '#return_value' => "1", |
| 1015 | '#default_value' => true, |
| 1016 | ); |
| 1017 | |
| 1018 | $form_term["term_row_mid".$itemname]=array("#value" => "</td><td>$orphaned_tagnode_term->name</td><td>"); |
| 1019 | $vocab = taxonomy_get_vocabulary($orphaned_tagnode_term->vid); |
| 1020 | $form_term["term_row_name".$itemname]=array("#value" => "$vocab->name"); |
| 1021 | $form_term["term_row_end".$itemname]=array("#value" => "</td></tr>"); |
| 1022 | } |
| 1023 | $form_term["term_submit_row_start"]=array("#value" => "<tr><td colspan='3' align='center'>"); |
| 1024 | $form_term["orphan_tagnode_term_submit"]=array("#type"=>"submit", "#value" => "submit"); |
| 1025 | $form_term["term_submit_row_end"]=array("#value" => "</td></tr>"); |
| 1026 | $form_term["orphaned_tagnode_terms"]=array("#type"=>"hidden", "#value" => _utility_tagnode_array_to_url_string($orphaned_tagnode_terms)); |
| 1027 | $form_term["orphaned_tagnode_term_names"]=array("#type"=>"hidden", "#value" => _utility_tagnode_array_to_url_string($orphaned_tagnode_term_names)); |
| 1028 | |
| 1029 | $form_term["term_table_end"]=array("#value" => "</table><br><b>".t("Delete")."</b>': ".t("The term will be deleted.")); |
| 1030 | |
| 1031 | } else {//ELSE more than 0 results? Show table/form to delete orphaned tagnode terms |
| 1032 | $text_term .= t("There are no orphaned terms."); |
| 1033 | }//END more than 0 results? Show table/form to delete orphaned tagnode terms |
| 1034 | |
| 1035 | |
| 1036 | // *************ORPHANED TERM: RENDER OUTPUT**************************** |
| 1037 | if (strlen($text_term)===0) $text_term = drupal_get_form("form_orphan_tagnode_term", $form_term); |
| 1038 | |
| 1039 | $page_html.= theme("box",t("Orphaned Tagnode Terms"), $text_term); |
| 1040 | return $page_html; |
| 1041 | }//END function _maintain_tagnodes |
| 1042 | |
| 1043 | /** |
| 1044 | * process the form_orphan_tagnode_node form |
| 1045 | */ |
| 1046 | function form_orphan_tagnode_node_confirm () { |
| 1047 | //watchdog("content","Again3 Running form_orphan_tagnode_node_submit()"); |
| 1048 | //_utility_tagnode_debug("form=$form_id",$form_values); |
| 1049 | $form_values = $_POST["edit"]; |
| 1050 | if (!isset($form_values["orphaned_tagnode_nodes"])) drupal_goto("admin/settings/tagnode"); |
| 1051 | |
| 1052 | $confirmform = array(); |
| 1053 | $confirmform["#action"] = "tagnode/node/commit"; |
| 1054 | $orphaned_tagnode_nodes_str = $form_values["orphaned_tagnode_nodes"]; |
| 1055 | $orphaned_tagnode_node_titles_str = $form_values["orphaned_tagnode_node_titles"]; |
| 1056 | |
| 1057 | $submitted_orphaned_tagnode_nodes = _utility_tagnode_url_string_to_array($orphaned_tagnode_nodes_str); |
| 1058 | $submitted_orphaned_tagnode_node_titles = _utility_tagnode_url_string_to_array($orphaned_tagnode_node_titles_str); |
| 1059 | $orphaned_tagnode_nodes_to_fix = array(); |
| 1060 | $orphaned_tagnode_node_titles_to_fix = array(); |
| 1061 | $orphaned_tagnode_nodes_to_delete = array(); |
| 1062 | $orphaned_tagnode_node_titles_to_delete = array(); |
| 1063 | $counter = -1; |
| 1064 | |
| 1065 | foreach($submitted_orphaned_tagnode_nodes as $s_o_t_nid) { |
| 1066 | $counter = $counter + 1; |
| 1067 | $fixvar = "orphan_tagnode_node_fix_".$s_o_t_nid; |
| 1068 | $deletevar = "orphan_tagnode_node_delete_".$s_o_t_nid; |
| 1069 | if ($form_values[$fixvar]) { |
| 1070 | $orphaned_tagnode_nodes_to_fix[] = $s_o_t_nid; |
| 1071 | $orphaned_tagnode_node_titles_to_fix[$counter] = |
| 1072 | $submitted_orphaned_tagnode_node_titles[$counter]; |
| 1073 | } else { |
| 1074 | if ($form_values[$deletevar]) { |
| 1075 | $orphaned_tagnode_nodes_to_delete[] = $s_o_t_nid; |
| 1076 | $orphaned_tagnode_node_titles_to_delete[$counter] = $submitted_orphaned_tagnode_node_titles[$counter]; |
| 1077 | } |
| 1078 | } |
| 1079 | }//Loop back |
| 1080 | |
| 1081 | //if no boxes were checked, maintain tagnodes page |
| 1082 | if (count($orphaned_tagnode_nodes_to_fix)==0 && count($orphaned_tagnode_nodes_to_delete)==0) drupal_goto("admin/settings/tagnode"); |
| 1083 | |
| 1084 | //4.6 $extraform = form_hidden("confirm_orphaned_tagnode_nodes_fix",_utility_tagnode_array_to_url_string($orphaned_tagnode_nodes_to_fix)); |
| 1085 | $confirmform["confirm_orphaned_tagnode_nodes_fix"] = array( |
| 1086 | '#type' => "hidden", |
| 1087 | '#value' => _utility_tagnode_array_to_url_string($orphaned_tagnode_nodes_to_fix)); |
| 1088 | $confirmform["confirm_orphaned_tagnode_nodes_delete"] = array( |
| 1089 | '#type' => "hidden", |
| 1090 | '#value' => _utility_tagnode_array_to_url_string($orphaned_tagnode_nodes_to_delete)); |
| 1091 | $confirmquestion = t("Are you sure you want to... "); |
| 1092 | $description = ""; |
| 1093 | if ($orphaned_tagnode_nodes_to_fix) { |
| 1094 | $description .= "<h3>".t("fix these nodes").":</h3>"; |
| 1095 | $description .= _utility_tagnode_array_to_html_list($orphaned_tagnode_node_titles_to_fix); |
| 1096 | } |
| 1097 | if ($orphaned_tagnode_nodes_to_delete) { |
| 1098 | $description .= "<h3>".t("DELETE these nodes").":</h3>"; |
| 1099 | $description .= _utility_tagnode_array_to_html_list($orphaned_tagnode_node_titles_to_delete); |
| 1100 | } |
| 1101 | $description .= "<br><b>".t("This action cannot be undone.")."<b><br>"; |
| 1102 | //_utility_tagnode_debug("Tagnode Confirm Form",$confirmform); |
| 1103 | return confirm_form("form_orphan_tagnode_node_confirm", $confirmform, $confirmquestion, "admin/settings/tagnode", $description, t("OK"), t("cancel"), 'form_orphan_tagnode_node_confirm'); |
| 1104 | } |
| 1105 | |
| 1106 | /** |
| 1107 | * Fixes &/or deletes orphaned tagnode nodes (after confirm form) |
| 1108 | */ |
| 1109 | function form_orphan_tagnode_node_commit() { |
| 1110 | $form_values = $_POST["edit"]; |
| 1111 | if (!isset($form_values["confirm_orphaned_tagnode_nodes_fix"]) && !isset($form_values["confirm_orphaned_tagnode_nodes_delete"])) drupal_goto("admin/settings/tagnode"); |
| 1112 | |
| 1113 | $confirm_orphaned_tagnode_nodes_fix = $form_values["confirm_orphaned_tagnode_nodes_fix"]; |
| 1114 | $confirm_orphaned_tagnode_nodes_delete = $form_values["confirm_orphaned_tagnode_nodes_delete"]; |
| 1115 | if ($confirm_orphaned_tagnode_nodes_fix) { |
| 1116 | // *************** CONFIRMED ORPAHNED TAGNODE NODE FIX ********************* |
| 1117 | $fix_nodes = _utility_tagnode_url_string_to_array($confirm_orphaned_tagnode_nodes_fix); |
| 1118 | //_utility_tagnode_debug("fix_nodes",$fix_nodes); |
| 1119 | foreach ($fix_nodes as $nid_str) { |
| 1120 | $nid = (int)$nid_str; |
| 1121 | //get the vocabulary & the title for this node |
| 1122 | $thisnode = db_fetch_object(db_query("SELECT n.title, n.type FROM {node} n where nid = %d",$nid)); |
| 1123 | //$thisnode = node_load($nid); |
| 1124 | //_utility_tagnode_debug("node $nid is numeric?",is_numeric($nid)); |
| 1125 | //_utility_tagnode_debug("node $nid",$thisnode); |
| 1126 | $vid = (int)_get_tagnode_vid($thisnode->type); |
| 1127 | //insert the new term |
| 1128 | $newterm = array(); |
| 1129 | $newterm["name"] = $thisnode->title; |
| 1130 | $newterm["vid"] = $vid; |
| 1131 | $newterm["weight"] = 0; |
| 1132 | $newterm["tagnode"] = true; |
| 1133 | $status = taxonomy_save_term($newterm); |
| 1134 | } |
| 1135 | } |
| 1136 | |
| 1137 | if ($confirm_orphaned_tagnode_nodes_delete) { |
| 1138 | // *************** CONFIRMED ORPAHNED TAGNODE NODE DELETE ********************* |
| 1139 | $delete_nodes = _utility_tagnode_url_string_to_array($confirm_orphaned_tagnode_nodes_delete); |
| 1140 | foreach ($delete_nodes as $nid_str) { |
| 1141 | $nid = (int)$nid_str; |
| 1142 | $deletenode = array(); |
| 1143 | $deletenode["nid"] = $nid; |
| 1144 | $deletenode["confirm"] = "1"; |
| 1145 | //4.6 node_delete($deletenode); |
| 1146 | node_delete($nid); |
| 1147 | } |
| 1148 | } |
| 1149 | |
| 1150 | return _maintain_tagnodes(); |
| 1151 | } |
| 1152 | |
| 1153 | /** |
| 1154 | * Renders confirm form for deleting orphaned tagnode terms |
| 1155 | */ |
| 1156 | function form_orphan_tagnode_term_confirm () { |
| 1157 | //watchdog("content","Again3 Running form_orphan_tagnode_node_submit()"); |
| 1158 | |
| 1159 | $form_values = $_POST["edit"]; |