We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 32241
    • 1,495 Posts
    Will this be comited on the next release 0.9.2?
      Wendy Novianto
      [font=Verdana]PT DJAMOER Technology Media
      [font=Verdana]Xituz Media
      • 13577
      • 302 Posts
      Hmm.. I thought this sounded awfully familiar. Great! Can’t wait for this to be in a released version!! Good work guys.
        Standard Disclaimer
        I could be totally wrong.
        • 32963
        • 1,732 Posts
        Very nice work netnoise smiley
          xWisdom
          www.xwisdomhtml.com
          The fear of the Lord is the beginning of wisdom:
          MODx Co-Founder - Create and do more with less.
          • 32963
          • 1,732 Posts
          netnoise,

          It appears (haven’t try tried it as yet) to me that the above code only works on top-level folders, correct?

          I’m not sure if it works on folders/documents that are deeply nested.

            xWisdom
            www.xwisdomhtml.com
            The fear of the Lord is the beginning of wisdom:
            MODx Co-Founder - Create and do more with less.
            • 32758
            • 7 Posts
            Hello.
            Why didn’t I find this til it was too late ! huh
            I have just done my own version of this mod.

            Has this been incorporated yet ?
            My version DOES work several levels deep (tested down to 4 or 5), though it is working more-or-less the same way.
            Not sure from looking whether NetNoises code made all the editable docs appear in the root - Mine just displays the folders which contain editable docs (even if they are several folders deep) so the user can expand them.

            Only issues now occur when the user tries to edit a doc they do not have permissions for - system returns "No document found" error, rather than "You do not have permission" but that doesn’t bother me on my system.
            One day (soon I hope) I will get something on here that has not been done before !
              • 21255
              • 215 Posts
              Please post your code and let us see how you solved that problem wink
                • 32758
                • 7 Posts
                OK - Here’s my code.

                In /manager/frames/3ldr.php
                This is replacement for the makeHTML function.

                My basic idea is to 1st extract every docID plus its parents from the db and store as array - This is the first additional db call that I make.

                Next make a call to get the every docID that the user has access to. This is the 2nd additional call

                Now build a list of all the docIDs that lie between the accessible docID and the $parent docID as passed to the function - these are the docs which need to be displayed to allow the user to navigate to his doc.
                Modify the original sql statement so that it requests these extra docs regardless of their edit/access permissions.

                At the moment I just build a comma separated string for the additional docIDs - There is probably a better / more efficient way to do this.

                I have done some limited testing - and it seems to satisfy my needs (eg an editor with access only to docs which are 3/4 folders deep in the tree can browse to his folders, without seeing the whole tree.

                Hope this helps !

                My only other thoughts are:-
                On a large site the 1st request to get every docID plus parent could be a problem.
                Did I read recently that there is a global in the API which stores the tree?
                If so, then I should probably use this instead of requesting it myself.

                function makeHTML($indent,$parent,$expandAll)
                 {
                  global $icons;
                  global $modxDBConn, $output, $dbase, $table_prefix, $_lang, $opened, $opened2, $closed2; //added global vars
                  $pad = "     ";
                  
                  // setup spacer
                  $spacer = "";
                  for ($i = 1; $i <= $indent; $i++){
                   $spacer .= "     ";
                  }
                 
                
                  // Raymond: query other documents,set default sort order 
                  $orderby = "isfolder DESC";
                  if(isset($_SESSION['tree_sortby']) && isset($_SESSION['tree_sortdir'])) {
                   $orderby = $_SESSION['tree_sortby']." ".$_SESSION['tree_sortdir'];
                  } else {
                   $_SESSION['tree_sortby'] = 'isfolder';
                   $_SESSION['tree_sortdir'] = 'DESC';
                  }
                        if($_SESSION['tree_sortby'] == 'isfolder') $orderby .= ", menuindex ASC, pagetitle";
                  //Raymond: end
                 
                
                  $tblsc = $dbase.".".$table_prefix."site_content";
                  $tbldg = $dbase.".".$table_prefix."document_groups";
                  $tbldgn = $dbase.".".$table_prefix."documentgroup_names";
                  // get document groups for current user
                  if($_SESSION['mgrDocgroups']) $docgrp = implode(",",$_SESSION['mgrDocgroups']);
                  $access = "1='".$_SESSION['mgrRole']."' OR sc.privatemgr=0".
                      (!$docgrp ? "":" OR dg.document_group IN ($docgrp)");
                //**********************
                //wyn  Fetch list of all documents plus parents
                $MainAddList='';
                  $sql = "SELECT id, parent FROM $tblsc";
                  $result = mysql_query($sql, $modxDBConn);
                 //wyn store all docs and parents in array
                  while(list($id,$thisparent) = mysql_fetch_row($result))
                  {
                   $parentarray[$id]=$thisparent;
                  }
                //wyn now select all docs the user is allowed to access
                  $sql = "SELECT DISTINCT sc.id 
                    FROM $tblsc AS sc 
                    LEFT JOIN $tbldg dg on dg.document = sc.id
                    WHERE ($access) 
                    ORDER BY $orderby";
                  $result = mysql_query($sql, $modxDBConn);
                
                //wyn go through each doc and generate a list of all its parents
                //wyn at the moment I am just building a string of comma seperated id numbers.  
                //wyn There is probably a better way to do this !
                  while (list($id) = mysql_fetch_row($result)) {
                   $addlist='';
                   
                //wyn First go up through the tree, adding doc ids to $addlist until we reach $parent
                   while ($id) {
                    $thisparent=$parentarray[$id];
                    if ($thisparent==$parent) {
                     $addlist.=",$id,";
                     break;
                    }
                    $id=$thisparent;
                   }
                   
                //wyn Now add each element from $AddList into $MainAddList (if it is not already there)
                   if ($thisparent == $parent) {
                    if (strlen($addlist)) {
                     $addlist=str_replace(',,',',',$addlist);
                     $addlist=substr($addlist,1,-1);
                     $addlist=explode(',',$addlist);
                     foreach ($addlist as $thisid) {
                      if (strpos($MainAddList,",$thisid,")===false) {
                       $MainAddList .= ",$thisid,";
                      }
                     }
                    }
                    
                   }
                  }
                //wyn Tidy up $MainAddList to remove double commas etc
                  if (strlen($MainAddList)) {
                   $MainAddList=str_replace(',,',',',$MainAddList);
                   $MainAddList=substr($MainAddList,1,-1);
                  }
                      
                //******************************      
                  $sql = "SELECT DISTINCT sc.id, pagetitle, parent, isfolder, published, deleted, type, menuindex, hidemenu, alias, contentType, privateweb, privatemgr 
                    FROM $tblsc AS sc 
                    LEFT JOIN $tbldg dg on dg.document = sc.id
                    WHERE ((parent=$parent) 
                    AND ($access)) ";
                //wyn  Also make it fetch any docs included in $MainAddList
                  if (strlen($MainAddList)) {
                     $sql.="OR sc.id IN ($MainAddList) " ;
                    }  
                  $sql .=  "ORDER BY $orderby";
                  $result = mysql_query($sql, $modxDBConn);
                  if(mysql_num_rows($result)==0) {
                   $output .= '<div style="white-space: nowrap;">'.$spacer.$pad.'<img align="absmiddle" src="media/images/tree/deletedpage.gif" width="18" height="18"> <span class="emptyNode">'.$_lang['empty_folder'].'</span></div>';
                  }
                
                
                  while(list($id,$pagetitle,$parent,$isfolder,$published,$deleted,$type,$menuindex,$hidemenu,$alias,$contenttype,$privateweb,$privatemgr) = mysql_fetch_row($result))
                  {
                
                   $pagetitle = htmlspecialchars($pagetitle);
                   $pagetitleDisplay = $published==0 ? "<span class='unpublishedNode'>$pagetitle</span>" : ($hidemenu==1 ? "<span class='notInMenuNode'>$pagetitle</span>":"<span class='publishedNode'>$pagetitle</span>");
                   $pagetitleDisplay = $deleted==1 ? "<span class='deletedNode'>$pagetitle</span>" : $pagetitleDisplay;
                   $weblinkDisplay = $type=="reference" ? ' <img align="absmiddle" src="media/images/tree/web.gif">' : '' ;
                 
                
                   $alt = !empty($alias) ? $_lang['alias'].": ".$alias : $_lang['alias'].": - ";
                   $alt.= "\n".$_lang['document_opt_menu_index'].": ".$menuindex;
                   $alt.= "\n".$_lang['document_opt_show_menu'].": ".($hidemenu==1 ? $_lang['no']:$_lang['yes']);
                   $alt.= "\n".$_lang['page_data_web_access'].": ".($privateweb ? $_lang['private']:$_lang['public']);
                   $alt.= "\n".$_lang['page_data_mgr_access'].": ".($privatemgr ? $_lang['private']:$_lang['public']);
                 
                   if (!$isfolder) {
                    $icon='page';
                    if($privateweb||$privatemgr) $icon='page-secure';
                    else if(isset($icons[$contenttype])) $icon = $icons[$contenttype];
                    $output .= '<div id="node'.$id.'" p="'.$parent.'" style="white-space: nowrap;">'.$spacer.$pad.'<img id="p'.$id.'" align="absmiddle" title="'.$_lang['click_to_context'].'" style="cursor: pointer" src="media/images/tree/'.$icon.'.gif" width="18" height="18" onclick="showPopup('.$id.',\''.addslashes($pagetitle).'\',event);return false;" oncontextmenu="this.onclick(event);return false;" onmouseover="setCNS(this, 1)" onmouseout="setCNS(this, 0)" onmousedown="itemToChange='.$id.'; selectedObjectName=\''.addslashes($pagetitle).'\'; selectedObjectDeleted='.$deleted.';" /> ';
                    $output .= '<span p="'.$parent.'" onclick="treeAction('.$id.', \''.addslashes($pagetitle).'\'); setSelected(this);" onmouseover="setHoverClass(this, 1);" onmouseout="setHoverClass(this, 0);" class="treeNode" onmousedown="itemToChange='.$id.'; selectedObjectName=\''.addslashes($pagetitle).'\'; selectedObjectDeleted='.$deleted.';" oncontextmenu="document.getElementById(\'p'.$id.'\').onclick(event);return false;" title="'.addslashes($alt).'">'.$pagetitleDisplay.$weblinkDisplay.'</span> <small>('.$id.')</small></div>';
                   }
                   else {
                    //
                    // Jeroen add the expandAll 2 type for partial expansion
                    //    
                    if ($expandAll ==1 || ($expandAll == 2 && in_array($id, $opened)))
                    {
                     if ($expandAll == 1) {
                        array_push($opened2, $id);
                     }
                     $icon='folderopen';
                     $output .= '<div id="node'.$id.'" p="'.$parent.'" style="white-space: nowrap;">'.$spacer.'<img id="s'.$id.'" align="absmiddle" style="cursor: pointer" src="media/images/tree/minusnode.gif" width="18" height="18" onclick="toggleNode(this,'.($indent+1).','.$id.',0); return false;" oncontextmenu="this.onclick(event); return false;" /> <img id="f'.$id.'" align="absmiddle" title="'.$_lang['click_to_context'].'" style="cursor: pointer" src="media/images/tree/'.$icon.'.gif" width="18" height="18" onclick="showPopup('.$id.',\''.addslashes($pagetitle).'\',event);return false;" oncontextmenu="this.onclick(event);return false;" onmouseover="setCNS(this, 1)" onmouseout="setCNS(this, 0)" onmousedown="itemToChange='.$id.'; selectedObjectName=\''.addslashes($pagetitle).'\'; selectedObjectDeleted='.$deleted.';" /> ';
                     $output .= '<span onclick="treeAction('.$id.', \''.addslashes($pagetitle).'\'); setSelected(this);" onmouseover="setHoverClass(this, 1);" onmouseout="setHoverClass(this, 0);" class="treeNode" onmousedown="itemToChange='.$id.'; selectedObjectName=\''.addslashes($pagetitle).'\'; selectedObjectDeleted='.$deleted.';" oncontextmenu="document.getElementById(\'f'.$id.'\').onclick(event);return false;" title="'.addslashes($alt).'">'.$pagetitleDisplay.$weblinkDisplay.'</span> <small>('.$id.')</small><div style="display:block">';
                     makeHTML($indent+1,$id,$expandAll);
                     $output .= '</div></div>';
                    }
                    else {
                     $icon='folder';
                     $output .= '<div id="node'.$id.'" p="'.$parent.'" style="white-space: nowrap;">'.$spacer.'<img id="s'.$id.'" align="absmiddle" style="cursor: pointer" src="media/images/tree/plusnode.gif" width="18" height="18" onclick="toggleNode(this,'.($indent+1).','.$id.',0); return false;" oncontextmenu="this.onclick(event); return false;" /> <img id="f'.$id.'" title="'.$_lang['click_to_context'].'" align="absmiddle" style="cursor: pointer" src="media/images/tree/'.$icon.'.gif" width="18" height="18" onclick="showPopup('.$id.',\''.addslashes($pagetitle).'\',event);return false;" oncontextmenu="this.onclick(event);return false;" onmouseover="setCNS(this, 1)" onmouseout="setCNS(this, 0)" onmousedown="itemToChange='.$id.'; selectedObjectName=\''.addslashes($pagetitle).'\'; selectedObjectDeleted='.$deleted.';" /> ';
                     $output .= '<span onclick="treeAction('.$id.', \''.addslashes($pagetitle).'\'); setSelected(this);" onmouseover="setHoverClass(this, 1);" onmouseout="setHoverClass(this, 0);" class="treeNode" onmousedown="itemToChange='.$id.'; selectedObjectName=\''.addslashes($pagetitle).'\'; selectedObjectDeleted='.$deleted.';" oncontextmenu="document.getElementById(\'f'.$id.'\').onclick(event);return false;" title="'.addslashes($alt).'">'.$pagetitleDisplay.$weblinkDisplay.'</span> <small>('.$id.')</small><div style="display:none"></div></div>';
                     array_push($closed2, $id);
                    }
                    //
                    // Jeroen end
                    //
                   }
                   //
                   // Jeroen stores vars in Javascript
                   //
                      if ($expandAll == 1) {
                       echo '<script language="JavaScript"> ';
                       foreach ($opened2 as $item) {
                          printf("parent.openedArray[%d] = 1; ", $item);
                       }
                       echo '</script> ';
                      } elseif ($expandAll == 0) {
                       echo '<script language="JavaScript"> ';
                       foreach ($closed2 as $item) {
                          printf("parent.openedArray[%d] = 0; ", $item);
                       }
                       echo '</script> ';
                      }
                   //
                   // Jeroen end
                   //
                  }
                    }