r1643 + "still" isn't always the right expression
[racktables] / inc / functions.php
index 2350762cc805ff840e3ebeb82ec63e8237d38546..2a2f1ba0119f4c7e038343221ce9a6287dad4627 100644 (file)
@@ -57,6 +57,10 @@ function rectHeight ($rackData, $startRow, $template_idx)
                        {
                                if (isset ($rackData[$startRow - $height][$locidx]['skipped']))
                                        break 2;
+                               if (isset ($rackData[$startRow - $height][$locidx]['rowspan']))
+                                       break 2;
+                               if (isset ($rackData[$startRow - $height][$locidx]['colspan']))
+                                       break 2;
                                if ($rackData[$startRow - $height][$locidx]['state'] != 'T')
                                        break 2;
                                if ($object_id == 0)
@@ -71,7 +75,9 @@ function rectHeight ($rackData, $startRow, $template_idx)
                $height++;
        }
        while ($startRow - $height > 0);
-//     echo "for startRow==${startRow} and template==(${template[0]}, ${template[1]}, ${template[2]}) height==${height}<br>\n";
+#      echo "for startRow==${startRow} and template==(" . ($template[$template_idx][0] ? 'T' : 'F');
+#      echo ', ' . ($template[$template_idx][1] ? 'T' : 'F') . ', ' . ($template[$template_idx][2] ? 'T' : 'F');
+#      echo ") height==${height}<br>\n";
        return $height;
 }
 
@@ -88,14 +94,16 @@ function markSpan (&$rackData, $startRow, $maxheight, $template_idx)
                        if ($template[$template_idx][$locidx])
                        {
                                // Add colspan/rowspan to the first row met and mark the following ones to skip.
+                               // Explicitly show even single-cell spanned atoms, because rectHeight()
+                               // is expeciting this data for correct calculation.
                                if ($colspan != 0)
                                        $rackData[$startRow - $height][$locidx]['skipped'] = TRUE;
                                else
                                {
                                        $colspan = $templateWidth[$template_idx];
-                                       if ($colspan > 1)
+                                       if ($colspan >= 1)
                                                $rackData[$startRow - $height][$locidx]['colspan'] = $colspan;
-                                       if ($maxheight > 1)
+                                       if ($maxheight >= 1)
                                                $rackData[$startRow - $height][$locidx]['rowspan'] = $maxheight;
                                }
                        }
@@ -104,44 +112,52 @@ function markSpan (&$rackData, $startRow, $maxheight, $template_idx)
        return;
 }
 
-// This function finds rowspan/solspan/skipped atom attributes for renderRack()
-// What we actually have to do is to find all possible rectangles for each objects
-// and then find the widest of those with the maximal square.
+// This function sets rowspan/solspan/skipped atom attributes for renderRack()
+// What we actually have to do is to find _all_ possible rectangles for each unit
+// and then select the widest of those with the maximal square.
 function markAllSpans (&$rackData = NULL)
 {
        if ($rackData == NULL)
        {
-               showError ('Invalid rackData in markupAllSpans()');
+               showError ('Invalid rackData', __FUNCTION__);
                return;
        }
        for ($i = $rackData['height']; $i > 0; $i--)
+               while (markBestSpan ($rackData, $i));
+}
+
+// Calculate height of 6 possible span templates (array is presorted by width
+// descending) and mark the best (if any).
+function markBestSpan (&$rackData, $i)
+{
+       global $template, $templateWidth;
+       for ($j = 0; $j < 6; $j++)
        {
-               // calculate height of 6 possible span templates (array is presorted by width descending)
-               global $template;
-               for ($j = 0; $j < 6; $j++)
-                       $height[$j] = rectHeight ($rackData, $i, $j);
-               // find the widest rectangle of those with maximal height
-               $maxheight = max ($height);
-               if ($maxheight > 0)
+               $height[$j] = rectHeight ($rackData, $i, $j);
+               $square[$j] = $height[$j] * $templateWidth[$j];
+       }
+       // find the widest rectangle of those with maximal height
+       $maxsquare = max ($square);
+       if (!$maxsquare)
+               return FALSE;
+       $best_template_index = 0;
+       for ($j = 0; $j < 6; $j++)
+               if ($square[$j] == $maxsquare)
                {
-                       $best_template_index = 0;
-                       for ($j = 0; $j < 6; $j++)
-                               if ($height[$j] == $maxheight)
-                               {
-                                       $best_template_index = $j;
-                                       break;
-                               }
-                       // distribute span marks
-                       markSpan ($rackData, $i, $maxheight, $best_template_index);
+                       $best_template_index = $j;
+                       $bestheight = $height[$j];
+                       break;
                }
-       }
+       // distribute span marks
+       markSpan ($rackData, $i, $bestheight, $best_template_index);
+       return TRUE;
 }
 
 function delRow ($row_id = 0)
 {
        if ($row_id == 0)
        {
-               showError ('Not all required args to delRow() are present.');
+               showError ('Not all required args are present.', __FUNCTION__);
                return;
        }
        if (!isset ($_REQUEST['confirmed']) || $_REQUEST['confirmed'] != 'true')
@@ -154,7 +170,7 @@ function delRow ($row_id = 0)
        $result = $dbxlink->query ("update RackRow set deleted = 'yes' where id=${row_id} limit 1");
        if ($result->rowCount() != 1)
        {
-               showError ('Marked ' . $result.rowCount() . ' rows as deleted, but expected 1');
+               showError ('Marked ' . $result.rowCount() . ' rows as deleted, but expected 1', __FUNCTION__);
                return;
        }
        echo 'OK<br>';
@@ -166,7 +182,7 @@ function delRack ($rack_id = 0)
 {
        if ($rack_id == 0)
        {
-               showError ('Not all required args to delRack() are present.');
+               showError ('Not all required args are present.', __FUNCTION__);
                return;
        }
        if (!isset ($_REQUEST['confirmed']) || $_REQUEST['confirmed'] != 'true')
@@ -179,7 +195,7 @@ function delRack ($rack_id = 0)
        $result = $dbxlink->query ("update Rack set deleted = 'yes' where id=${rack_id} limit 1");
        if ($result->rowCount() != 1)
        {
-               showError ('Marked ' . $result.rowCount() . ' rows as deleted, but expected 1');
+               showError ('Marked ' . $result.rowCount() . ' rows as deleted, but expected 1', __FUNCTION__);
                return;
        }
        echo 'OK<br>';
@@ -191,7 +207,7 @@ function delObject ($object_id = 0)
 {
        if ($object_id == 0)
        {
-               showError ('Not all required args to delObject() are present.');
+               showError ('Not all required args are present.', __FUNCTION__);
                return;
        }
        if (!isset ($_REQUEST['confirmed']) || $_REQUEST['confirmed'] != 'true')
@@ -204,7 +220,7 @@ function delObject ($object_id = 0)
        $result = $dbxlink->query ("update RackObject set deleted = 'yes' where id=${object_id} limit 1");
        if ($result->rowCount() != 1)
        {
-               showError ('Marked ' . $result.rowCount() . ' rows as deleted, but expected 1');
+               showError ('Marked ' . $result.rowCount() . ' rows as deleted, but expected 1', __FUNCTION__);
                return;
        }
        echo 'OK<br>';
@@ -534,23 +550,23 @@ function getIPAddress ($ip=0)
        $ret['name'] = '';
        $ret['reserved'] = 'no';
        global $dbxlink;
-       $query =
+       $query1 =
                "select ".
                "name, reserved ".
                "from IPAddress ".
                "where ip = INET_ATON('$ip') and (reserved = 'yes' or name != '')";
-       $result = $dbxlink->query ($query);
-       if ($result == NULL)
+       $result1 = $dbxlink->query ($query1);
+       if ($result1 == NULL)
                return NULL;
-       if ($row = $result->fetch (PDO::FETCH_ASSOC))
+       if ($row = $result1->fetch (PDO::FETCH_ASSOC))
        {
                $ret['exists'] = 1;
                $ret['name'] = $row['name'];
                $ret['reserved'] = $row['reserved'];
        }
-       $result->closeCursor();
+       $result1->closeCursor();
 
-       $query =
+       $query2 =
                "select ".
                "IPBonds.object_id as object_id, ".
                "IPBonds.name as name, ".
@@ -562,9 +578,9 @@ function getIPAddress ($ip=0)
                "where IPBonds.ip=INET_ATON('$ip') ".
                "and chapter_name = 'RackObjectType' " .
                "order by RackObject.id, IPBonds.name";
-       $result = $dbxlink->query ($query);
+       $result2 = $dbxlink->query ($query2);
        $count=0;
-       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+       while ($row = $result2->fetch (PDO::FETCH_ASSOC))
        {
                $ret['bonds'][$count]['object_id'] = $row['object_id'];
                $ret['bonds'][$count]['name'] = $row['name'];
@@ -577,7 +593,7 @@ function getIPAddress ($ip=0)
                $count++;
                $ret['exists'] = 1;
        }
-       $result->closeCursor();
+       $result2->closeCursor();
 
        return $ret;
 }
@@ -653,7 +669,7 @@ function mergeSearchResults (&$objects, $terms, $fieldname)
        $result = $dbxlink->query($query);
        if ($result == NULL)
        {
-               showError ("SQL query failed in mergeSearchResults()");
+               showError ("SQL query failed", __FUNCTION__);
                return NULL;
        }
 // FIXME: this dead call was executed 4 times per 1 object search!
@@ -731,7 +747,7 @@ function getPrevIDforRack ($row_id = 0, $rack_id = 0)
 {
        if ($row_id <= 0 or $rack_id <= 0)
        {
-               showError ('Invalid arguments passed to getPrevIDforRack()');
+               showError ('Invalid arguments passed', __FUNCTION__);
                return NULL;
        }
        $rackList = getRacksForRow ($row_id);
@@ -745,7 +761,7 @@ function getNextIDforRack ($row_id = 0, $rack_id = 0)
 {
        if ($row_id <= 0 or $rack_id <= 0)
        {
-               showError ('Invalid arguments passed to getNextIDforRack()');
+               showError ('Invalid arguments passed', __FUNCTION__);
                return NULL;
        }
        $rackList = getRacksForRow ($row_id);
@@ -1028,4 +1044,126 @@ function findAllEndpoints ($object_id, $fallback = '')
        return $regular;
 }
 
+// Some records in the dictionary may be written as plain text or as Wiki
+// link in the following syntax:
+// 1. word
+// 2. [[word URL]] // FIXME: this isn't working
+// 3. [[word word word | URL]]
+// This function parses the line and returns text suitable for either A
+// (rendering <A HREF>) or O (for <OPTION>).
+function parseWikiLink ($line, $which)
+{
+       if (preg_match ('/^\[\[.+\]\]$/', $line) == 0)
+               return $line;
+       $line = preg_replace ('/^\[\[(.+)\]\]$/', '$1', $line);
+       $s = explode ('|', $line);
+       $o_value = trim ($s[0]);
+       $a_value = trim ($s[1]);
+       if ($which == 'a')
+               return "<a href='${a_value}'>${o_value}</a>";
+       if ($which == 'o')
+               return $o_value;
+}
+
+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)
+{
+       if ($data == NULL)
+       {
+               showError ('Invalid argument', __FUNCTION__);
+               return NULL;
+       }
+       $counter = array ('A' => 0, 'U' => 0, 'T' => 0, 'W' => 0, 'F' => 0);
+       for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
+               for ($locidx = 0; $locidx < 3; $locidx++)
+                       $counter[$data[$unit_no][$locidx]['state']]++;
+       return ($counter['T'] + $counter['W'] + $counter['U']) / ($counter['T'] + $counter['W'] + $counter['U'] + $counter['F']);
+}
+
+// Same for row.
+function getRSUforRackRow ($rowData = NULL)
+{
+       if ($rowData == NULL)
+       {
+               showError ('Invalid argument', __FUNCTION__);
+               return NULL;
+       }
+       $counter = array ('A' => 0, 'U' => 0, 'T' => 0, 'W' => 0, 'F' => 0);
+       $total_height = 0;
+       foreach (array_keys ($rowData) as $rack_id)
+       {
+               $data = getRackData ($rack_id);
+               $total_height += $data['height'];
+               for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
+                       for ($locidx = 0; $locidx < 3; $locidx++)
+                               $counter[$data[$unit_no][$locidx]['state']]++;
+       }
+       return ($counter['T'] + $counter['W'] + $counter['U']) / ($counter['T'] + $counter['W'] + $counter['U'] + $counter['F']);
+}
+
+function getObjectCount ($rackData)
+{
+       $objects = array();
+       for ($i = $rackData['height']; $i > 0; $i--)
+               for ($locidx = 0; $locidx < 3; $locidx++)
+                       if
+                       (
+                               $rackData[$i][$locidx]['state'] == 'T' and
+                               !in_array ($rackData[$i][$locidx]['object_id'], $objects)
+                       )
+                               $objects[] = $rackData[$i][$locidx]['object_id'];
+       return count ($objects);
+}
+
+// Perform substitutions and return resulting string
+function apply_macros ($macros, $subject)
+{
+       $ret = $subject;
+       foreach ($macros as $search => $replace)
+               $ret = str_replace ($search, $replace, $ret);
+       return $ret;
+}
+
+// Make sure the string is always wrapped with LF characters
+function lf_wrap ($str)
+{
+       $ret = trim ($str, "\r\n");
+       if (!empty ($ret))
+               $ret .= "\n";
+       return $ret;
+}
+
+// Adopted from Mantis BTS code.
+function string_insert_hrefs ($s)
+{
+       if (getConfigVar ('DETECT_URLS') != 'yes')
+               return $s;
+       # Find any URL in a string and replace it by a clickable link
+       $s = preg_replace( '/(([[:alpha:]][-+.[:alnum:]]*):\/\/(%[[:digit:]A-Fa-f]{2}|[-_.!~*\';\/?%^\\\\:@&={\|}+$#\(\),\[\][:alnum:]])+)/se',
+               "'<a href=\"'.rtrim('\\1','.').'\">\\1</a> [<a href=\"'.rtrim('\\1','.').'\" target=\"_blank\">^</a>]'",
+               $s);
+       $s = preg_replace( '/\b' . email_regex_simple() . '\b/i',
+               '<a href="mailto:\0">\0</a>',
+               $s);
+       return $s;
+}
+
+// Idem.
+function email_regex_simple ()
+{
+       return "(([a-z0-9!#*+\/=?^_{|}~-]+(?:\.[a-z0-9!#*+\/=?^_{|}~-]+)*)" . # recipient
+       "\@((?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?))"; # @domain
+}
+
 ?>