r2906 - maintenance->trunk sync of changesets 2886~2894
[racktables] / inc / functions.php
index 045c0ac..bec0db3 100644 (file)
@@ -556,16 +556,6 @@ function sortObjectAddressesAndNames ($a, $b)
        return $objname_cmp;
 }
 
-function sortAddresses ($a, $b)
-{
-       $name_cmp = sortTokenize($a['name'], $b['name']);
-       if ($name_cmp == 0)
-       {
-               return sortTokenize($a['ip'], $b['ip']);
-       }
-       return $name_cmp;
-}
-
 // This function expands port compat list into a matrix.
 function buildPortCompatMatrixFromList ($portTypeList, $portCompatList)
 {
@@ -626,18 +616,6 @@ function parseWikiLink ($line, $which, $strip_optgroup = FALSE)
                return $o_value;
 }
 
-// FIXME: only renderIPv4Address() is using this function, consider
-// phasing it out.
-function buildVServiceName ($vsinfo = NULL)
-{
-       if ($vsinfo == NULL)
-       {
-               showError ('NULL argument', __FUNCTION__);
-               return NULL;
-       }
-       return $vsinfo['vip'] . ':' . $vsinfo['vport'] . '/' . $vsinfo['proto'];
-}
-
 // rackspace usage for a single rack
 // (T + W + U) / (height * 3 - A)
 function getRSUforRack ($data = NULL)
@@ -769,9 +747,10 @@ function pokeNode (&$tree, $trace, $key, $value, $threshold = 0)
 // key, which is in turn indexed by id. Functions, which are ready to handle
 // tree collapsion/expansion themselves, may request non-zero threshold value
 // for smaller resulting tree.
-function treeFromList ($nodelist, $threshold = 0, $return_main_payload = TRUE)
+function treeFromList (&$orig_nodelist, $threshold = 0, $return_main_payload = TRUE)
 {
        $tree = array();
+       $nodelist = $orig_nodelist;
        // Array equivalent of traceEntity() function.
        $trace = array();
        // set kidc and kids only once
@@ -811,10 +790,12 @@ function treeFromList ($nodelist, $threshold = 0, $return_main_payload = TRUE)
                }
        }
        while ($nextpass);
-       if ($return_main_payload)
-               return $tree;
-       else
+       if (!$return_main_payload)
                return $nodelist;
+       // update each input node with its backtrace route
+       foreach ($trace as $nodeid => $route)
+               $orig_nodelist[$nodeid]['trace'] = $route;
+       return $tree;
 }
 
 // Build a tree from the tag list and return everything _except_ the tree.
@@ -841,120 +822,25 @@ function serializeTags ($chain, $baseurl = '')
        return $ret;
 }
 
-// For each tag add all its parent tags onto the list. Don't expect anything
-// except user's tags on the chain.
-function getTagChainExpansion ($chain, $tree = NULL)
-{
-       $self = __FUNCTION__;
-       if ($tree === NULL)
-       {
-               global $tagtree;
-               $tree = $tagtree;
-       }
-       // For each tag find its path from the root, then combine items
-       // of all paths and add them to the chain, if they aren't there yet.
-       $ret = array();
-       foreach ($tree as $taginfo1)
-       {
-               $hit = FALSE;
-               foreach ($chain as $taginfo2)
-                       if ($taginfo1['id'] == $taginfo2['id'])
-                       {
-                               $hit = TRUE;
-                               break;
-                       }
-               if (count ($taginfo1['kids']) > 0)
-               {
-                       $subsearch = $self ($chain, $taginfo1['kids']);
-                       if (count ($subsearch))
-                       {
-                               $hit = TRUE;
-                               $ret = array_merge ($ret, $subsearch);
-                       }
-               }
-               if ($hit)
-                       $ret[] = $taginfo1;
-       }
-       return $ret;
-}
-
 // Return the list of missing implicit tags.
 function getImplicitTags ($oldtags)
 {
-       $ret = array();
-       $newtags = getTagChainExpansion ($oldtags);
-       foreach ($newtags as $newtag)
-       {
-               $already_exists = FALSE;
-               foreach ($oldtags as $oldtag)
-                       if ($newtag['id'] == $oldtag['id'])
-                       {
-                               $already_exists = TRUE;
-                               break;
-                       }
-               if ($already_exists)
-                       continue;
-               $ret[] = array ('id' => $newtag['id'], 'tag' => $newtag['tag'], 'parent_id' => $newtag['parent_id']);
-       }
-       return $ret;
+       global $taglist;
+       $tmp = array();
+       foreach ($oldtags as $taginfo)
+               $tmp = array_merge ($tmp, $taglist[$taginfo['id']]['trace']);
+       // don't call array_unique here, it is in the function we will call now
+       return buildTagChainFromIds ($tmp);
 }
 
 // Minimize the chain: exclude all implicit tags and return the result.
-function getExplicitTagsOnly ($chain, $tree = NULL)
-{
-       $self = __FUNCTION__;
-       global $tagtree;
-       if ($tree === NULL)
-               $tree = $tagtree;
-       $ret = array();
-       foreach ($tree as $taginfo)
-       {
-               if (isset ($taginfo['kids']))
-               {
-                       $harvest = $self ($chain, $taginfo['kids']);
-                       if (count ($harvest) > 0)
-                       {
-                               $ret = array_merge ($ret, $harvest);
-                               continue;
-                       }
-               }
-               // This tag isn't implicit, test is for being explicit.
-               foreach ($chain as $testtag)
-                       if ($taginfo['id'] == $testtag['id'])
-                       {
-                               $ret[] = $testtag;
-                               break;
-                       }
-       }
-       return $ret;
-}
-
-// Maximize the chain: for each tag add all tags, for which it is direct or indirect parent.
-// Unlike other functions, this one accepts and returns a list of integer tag IDs, not
-// a list of tag structures. Same structure (tag ID list) is returned after processing.
-function complementByKids ($idlist, $tree = NULL, $getall = FALSE)
+function getExplicitTagsOnly ($chain)
 {
-       $self = __FUNCTION__;
-       global $tagtree;
-       if ($tree === NULL)
-               $tree = $tagtree;
-       $getallkids = $getall;
        $ret = array();
-       foreach ($tree as $taginfo)
-       {
-               foreach ($idlist as $test_id)
-                       if ($getall or $taginfo['id'] == $test_id)
-                       {
-                               $ret[] = $taginfo['id'];
-                               // Once matched node makes all sub-nodes match, but don't make
-                               // a mistake of matching every other node at the current level.
-                               $getallkids = TRUE;
-                               break;
-                       }
-               if (isset ($taginfo['kids']))
-                       $ret = array_merge ($ret, $self ($idlist, $taginfo['kids'], $getallkids));
-               $getallkids = FALSE;
-       }
+       $big_backtrace = getImplicitTags ($chain);
+       foreach ($chain as $key => $taginfo)
+               if (!tagOnChain ($taginfo, $big_backtrace))
+                       $ret[$key] = $taginfo;
        return $ret;
 }
 
@@ -969,7 +855,7 @@ function generateEntityAutoTags ($cell)
                        $ret[] = array ('tag' => '$rackid_' . $cell['id']);
                        $ret[] = array ('tag' => '$any_rack');
                        break;
-               case 'object': // during transition bypass is already the whole structure
+               case 'object':
                        $ret[] = array ('tag' => '$id_' . $cell['id']);
                        $ret[] = array ('tag' => '$typeid_' . $cell['objtype_id']);
                        $ret[] = array ('tag' => '$any_object');
@@ -978,9 +864,19 @@ function generateEntityAutoTags ($cell)
                        if (!strlen ($cell['rack_id']))
                                $ret[] = array ('tag' => '$unmounted');
                        break;
-               case 'ipv4net': // during transition bypass is already the whole structure
+               case 'ipv4net':
                        $ret[] = array ('tag' => '$ip4netid_' . $cell['id']);
                        $ret[] = array ('tag' => '$ip4net-' . str_replace ('.', '-', $cell['ip']) . '-' . $cell['mask']);
+                       for ($i = 8; $i < 32; $i++)
+                       {
+                               // these conditions hit 1 to 3 times per each i
+                               if ($cell['mask'] >= $i)
+                                       $ret[] = array ('tag' => '$masklen_ge_' . $i);
+                               if ($cell['mask'] <= $i)
+                                       $ret[] = array ('tag' => '$masklen_le_' . $i);
+                               if ($cell['mask'] == $i)
+                                       $ret[] = array ('tag' => '$masklen_eq_' . $i);
+                       }
                        $ret[] = array ('tag' => '$any_ip4net');
                        $ret[] = array ('tag' => '$any_net');
                        break;
@@ -1008,6 +904,21 @@ function generateEntityAutoTags ($cell)
                default: // HCF!
                        break;
        }
+       // {$tagless} doesn't apply to users
+       switch ($cell['realm'])
+       {
+               case 'rack':
+               case 'object':
+               case 'ipv4net':
+               case 'ipv4vs':
+               case 'ipv4rspool':
+               case 'file':
+                       if (!count ($cell['etags']))
+                               $ret[] = array ('tag' => '$untagged');
+                       break;
+               default:
+                       break;
+       }
        return $ret;
 }
 
@@ -1031,17 +942,6 @@ function tagNameOnChain ($tagname, $tagchain)
        return FALSE;
 }
 
-// Idem, but use ID list instead of chain.
-function tagOnIdList ($taginfo, $tagidlist)
-{
-       if (!isset ($taginfo['id']))
-               return FALSE;
-       foreach ($tagidlist as $tagid)
-               if ($taginfo['id'] == $tagid)
-                       return TRUE;
-       return FALSE;
-}
-
 // Return TRUE, if two tags chains differ (order of tags doesn't matter).
 // Assume, that neither of the lists contains duplicates.
 // FIXME: a faster, than O(x^2) method is possible for this calculation.
@@ -1100,17 +1000,7 @@ function fixContext ()
                assertUIntArg ($page[$pageno]['bypass'], __FUNCTION__);
                $target_realm = $etype_by_pageno[$pageno];
                $target_id = $_REQUEST[$page[$pageno]['bypass']];
-               if (NULL === ($target = spotEntity ($target_realm, $target_id)))
-               {
-                       showError
-                               (
-                                       "The record you are requesting isn't in the database (any more)\n" .
-                                       "realm: '${target_realm}'\n" .
-                                       "id: '${target_id}'",
-                                       __FUNCTION__
-                               );
-                       die;
-               }
+               $target = spotEntity ($target_realm, $target_id);
                $target_given_tags = $target['etags'];
                // Don't reset autochain, because auth procedures could push stuff there in.
                // Another important point is to ignore 'user' realm, so we don't infuse effective
@@ -1138,31 +1028,31 @@ function buildTagChainFromIds ($tagidlist)
 
 // Process a given tag tree and return only meaningful branches. The resulting
 // (sub)tree will have refcnt leaves on every last branch.
-function getObjectiveTagTree ($tree, $realm)
+function getObjectiveTagTree ($tree, $realm, $preselect)
 {
        $self = __FUNCTION__;
        $ret = array();
        foreach ($tree as $taginfo)
        {
-               $subsearch = array();
-               $pick = FALSE;
-               if (count ($taginfo['kids']))
-               {
-                       $subsearch = $self ($taginfo['kids'], $realm);
-                       $pick = count ($subsearch) > 0;
-               }
-               if (isset ($taginfo['refcnt'][$realm]))
-                       $pick = TRUE;
-               if (!$pick)
-                       continue;
-               $ret[] = array
+               $subsearch = $self ($taginfo['kids'], $realm, $preselect);
+               // If the current node addresses something, add it to the result
+               // regardless of how many sub-nodes it features.
+               if
                (
-                       'id' => $taginfo['id'],
-                       'tag' => $taginfo['tag'],
-                       'parent_id' => $taginfo['parent_id'],
-                       'refcnt' => $taginfo['refcnt'],
-                       'kids' => $subsearch
-               );
+                       isset ($taginfo['refcnt'][$realm]) or
+                       count ($subsearch) > 1 or
+                       in_array ($taginfo['id'], $preselect)
+               )
+                       $ret[] = array
+                       (
+                               'id' => $taginfo['id'],
+                               'tag' => $taginfo['tag'],
+                               'parent_id' => $taginfo['parent_id'],
+                               'refcnt' => $taginfo['refcnt'],
+                               'kids' => $subsearch
+                       );
+               else
+                       $ret = array_merge ($ret, $subsearch);
        }
        return $ret;
 }
@@ -2030,7 +1920,7 @@ function scanRealmByText ($realm = NULL, $ftext = '')
                }
                return filterCellList (listCells ($realm), $fexpr);
        default:
-               return NULL;
+               throw new InvalidArgException ('$realm', $realm);
        }
 
 }
@@ -2064,8 +1954,8 @@ function constructUserCell ($username)
                'user_realname' => '',
                'etags' => array(),
                'itags' => array(),
-               'atags' => array(),
        );
+       $ret['atags'] = generateEntityAutoTags ($ret);
        return $ret;
 }