. * --------------------------------------------------------------------- **/ class PDU_Rack extends CommonDBRelation { static public $itemtype_1 = 'Rack'; static public $items_id_1 = 'racks_id'; static public $itemtype_2 = 'PDU'; static public $items_id_2 = 'pdus_id'; static public $checkItem_1_Rights = self::DONT_CHECK_ITEM_RIGHTS; static public $mustBeAttached_1 = false; static public $mustBeAttached_2 = false; const SIDE_LEFT = 1; const SIDE_RIGHT = 2; const SIDE_TOP = 3; const SIDE_BOTTOM = 4; static function getTypeName($nb = 0) { return _n('Item', 'Item', $nb); } function post_getEmpty() { $this->fields['bgcolor'] = '#FF9D1F'; } function getForbiddenStandardMassiveAction() { $forbidden = parent::getForbiddenStandardMassiveAction(); $forbidden[] = 'MassiveAction:update'; $forbidden[] = 'CommonDBConnexity:affect'; $forbidden[] = 'CommonDBConnexity:unaffect'; return $forbidden; } function prepareInputForAdd($input) { return $this->prepareInput($input); } function prepareInputForUpdate($input) { return $this->prepareInput($input); } /** * Prepares and check validity of input (for update and add) and * * @param array $input Input data * * @return array */ private function prepareInput($input) { $error_detected = []; $pdus_id = $this->fields['pdus_id']; $racks_id = $this->fields['racks_id']; $position = $this->fields['position']; $side = $this->fields['side']; //check for requirements if ($this->isNewItem()) { if (!isset($input['pdus_id'])) { $error_detected[] = __('A pdu is required'); } if (!isset($input['racks_id'])) { $error_detected[] = __('A rack is required'); } if (!isset($input['position'])) { $error_detected[] = __('A position is required'); } if (!isset($input['side'])) { $error_detected[] = __('A side is required'); } } if (isset($input['pdus_id'])) { $pdus_id = $input['pdus_id']; } if (isset($input['racks_id'])) { $racks_id = $input['racks_id']; } if (isset($input['position'])) { $position = $input['position']; } if (isset($input['side'])) { $side = $input['side']; } if (!count($error_detected)) { //check if required U are available at position $required_units = 1; $rack = new Rack; $rack->getFromDB($racks_id); $pdu = new PDU; $pdu->getFromDB($pdus_id); $filled = self::getFilled($rack, $side); $model = new PDUModel; if ($model->getFromDB($pdu->fields['pdumodels_id'])) { if ($model->fields['required_units'] > 1) { $required_units = $model->fields['required_units']; } } if (in_array($side, [self::SIDE_LEFT, self::SIDE_RIGHT]) && ($position > $rack->fields['number_units'] || $position + $required_units > $rack->fields['number_units'] + 1)) { $error_detected[] = __('Item is out of rack bounds'); } else { for ($i = 0; $i < $required_units; $i++) { if ($filled[$position + $i] > 0 && $filled[$position + $i] != $pdus_id) { $error_detected[] = __('Not enough space available to place item'); break; } } } } if (count($error_detected)) { foreach ($error_detected as $error) { Session::addMessageAfterRedirect( $error, true, ERROR ); } return false; } return $input; } /** * Get already filled places * @param Rack $rack The current rack * @param integer $side The side of rack to check * @return Array [position -> racks_id | 0] */ static function getFilled(Rack $rack, $side = 0) { $pdu = new PDU; $model = new PDUModel; $filled = array_fill(0, $rack->fields['number_units'], 0); $used = self::getForRackSide($rack, $side); foreach ($used as $current_pdu) { $required_units = 1; $pdu->getFromDB($current_pdu['pdus_id']); if (in_array($side, [self::SIDE_LEFT, self::SIDE_RIGHT]) && $model->getFromDB($pdu->fields['pdumodels_id'])) { if ($model->fields['required_units'] > 1) { $required_units = $model->fields['required_units']; } } for ($i = 0; $i <= $required_units; $i++) { $position = $current_pdu['position'] + $i; $filled[$position] = $current_pdu['pdus_id']; } } return $filled; } function showForm($ID, $options = []) { global $DB; // search used racked (or sided mounted) pdus $used = []; foreach ($DB->request([ 'FROM' => $this->getTable() ]) as $not_racked) { $used[] = $not_racked['pdus_id']; } foreach ($DB->request([ 'SELECT' => 'items_id', 'FROM' => Item_Rack::getTable(), 'WHERE' => [ 'itemtype' => 'PDU' ] ]) as $racked) { $used[] = $racked['items_id']; }; echo "
"; $this->initForm($ID, $options); $this->showFormHeader(); $rack = new Rack(); $rack->getFromDB($this->fields['racks_id']); $rand = mt_rand(); echo ""; echo ""; echo ""; PDU::dropdown([ 'value' => $this->fields["pdus_id"], 'rand' => $rand, 'used' => $used, 'entity' => $rack->fields['entities_id'], 'entity_sons' => $rack->fields['is_recursive'], ]); echo ""; echo ""; echo ""; Dropdown::showFromArray( 'side', self::getSides(), [ 'value' => $this->fields["side"], 'rand' => $rand, ] ); echo ""; echo ""; echo ""; echo ""; echo ""; Rack::dropdown(['value' => $this->fields["racks_id"], 'rand' => $rand]); echo ""; echo ""; echo ""; Dropdown::showNumber( 'position', [ 'value' => $this->fields["position"], 'min' => 1, 'max' => $rack->fields['number_units'], 'step' => 1, // 'used' => $rack->getFilled($this->fields['itemtype'], $this->fields['items_id']), 'rand' => $rand ] ); echo ""; echo ""; echo ""; echo ""; echo ""; Html::showColorField( 'bgcolor', [ 'value' => $this->fields['bgcolor'], 'rand' => $rand ] ); echo ""; echo ""; $this->showFormButtons($options); } static function showListForRack(Rack $rack) { global $DB; echo "

".__("Side pdus")."

"; $pdu = new PDU; $canedit = $rack->canEdit($rack->getID()); $rand = mt_rand(); $items = $DB->request([ 'FROM' => self::getTable(), 'WHERE' => [ 'racks_id' => $rack->getID() ] ]); if (!count($items)) { echo ""; echo "
".__('No item found')."
"; } else { if ($canedit) { Html::openMassiveActionsForm('mass'.__CLASS__.$rand); $massiveactionparams = [ 'num_displayed' => min($_SESSION['glpilist_limit'], count($items)), 'container' => 'mass'.__CLASS__.$rand ]; Html::showMassiveActions($massiveactionparams); } echo ""; $header = ""; if ($canedit) { $header .= ""; } $header .= ""; $header .= ""; $header .= ""; $header .= ""; echo $header; foreach ($items as $row) { if ($pdu->getFromDB($row['pdus_id'])) { echo ""; if ($canedit) { echo ""; } echo ""; echo ""; echo ""; echo ""; } } echo $header; echo "
"; $header .= Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); $header .= ""._n('Item', 'Items', 1)."".__('Side')."".__('Position')."
"; Html::showMassiveActionCheckBox(__CLASS__, $row["id"]); echo "".$pdu->getLink()."".self::getSideName($row['side'])."{$row['position']}
"; if ($canedit && count($items)) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); } if ($canedit) { Html::closeForm(); } } } static function showStatsForRack(Rack $rack) { global $DB, $CFG_GLPI; $pdu = new PDU; $pdu_m = new PDUModel; $pra = new self; $sides = self::getSides(); $found_pdus = []; // find pdus from this relation $iterator = $DB->request([ 'FROM' => self::getTable(), 'WHERE' => [ 'racks_id' => $rack->getID() ], 'ORDER' => 'side' ]); foreach ($iterator as $current) { $found_pdus[] = [ 'pdus_id' => $current['pdus_id'], 'racked' => false, 'position' => $current['position'], 'side' => $current['side'], 'bgcolor' => $current['bgcolor'], ]; } // find pdus from item_rack relation $iterator = $DB->request([ 'FROM' => Item_Rack::getTable(), 'WHERE' => [ 'racks_id' => $rack->getID(), 'itemtype' => 'PDU' ] ]); foreach ($iterator as $current) { $found_pdus[] = [ 'pdus_id' => $current['items_id'], 'racked' => true, 'position' => $current['position'], 'side' => false, 'bgcolor' => $current['bgcolor'], ]; } echo "
"; echo "

".__("Power units")."

"; echo "
"; if (count($found_pdus)) { echo ""; foreach ($found_pdus as $current_pdu) { if ($pdu->getFromDB($current_pdu['pdus_id'])) { $bg_color = $current_pdu['bgcolor']; $fg_color = !empty($current_pdu['bgcolor']) ? Html::getInvertedColor($current_pdu['bgcolor']) : ""; $fg_color_s = "color: $fg_color;"; echo ""; echo ""; echo ""; echo ""; echo ""; } } echo "
"; if ($current_pdu['racked']) { echo ""; } else { switch ($current_pdu['side']) { case self::SIDE_LEFT: echo ""; break; case self::SIDE_RIGHT: echo ""; break; case self::SIDE_TOP: echo ""; break; case self::SIDE_BOTTOM: echo ""; break; } } echo ""; echo "".$pdu->getName().""; echo ""; if ($pdu_m->getFromDB($pdu->fields['pdumodels_id'])) { echo ""; echo $pdu_m->fields['max_power']."W"; } echo "
"; } echo ""; echo ""; echo _sx('button', "Add"); echo ""; echo "
"; echo "
"; $ajax_url = $CFG_GLPI['root_doc']."/ajax/rack.php"; $js = <<getID()}", action: "show_pdu_form", ajax: true, }, success: function(data) { $('#grid-dialog') .html(data) .dialog({ modal: true, width: 'auto' }); } }); }); }); JAVASCRIPT; echo Html::scriptBlock($js); } static function showFirstForm($racks_id = 0) { $rand = mt_rand(); echo " "; Dropdown::showFromArray('sub_form', [ 'racked' => __('racked'), 'side_rack' => __('placed at rack side'), ], [ 'display_emptychoice' => true, 'on_change' => 'showAddPduSubForm()', 'rand' => $rand, ]); $pra_url = PDU_Rack::getFormURL()."?racks_id=$racks_id&ajax=true"; $ira_url = Item_Rack::getFormURL()."?_onlypdu=true&orientation=0&position=1&racks_id=$racks_id&ajax=true"; $js = <<
"; } static function showVizForRack(Rack $rack, $side) { global $CFG_GLPI; $rand = mt_rand(); $num_u = $rack->fields['number_units']; $pdu = new PDU; $pdu_m = new PDUModel; $rel = new self; $found_pdus_side = self::getForRackSide($rack, $side); // check if the rack has sided pdu on other side (to get symetrical view) $found_all_pdus_side = self::getForRackSide($rack, [$side, self::getOtherSide($side)]); $float = false; $add_class = "side_pdus_nofloat"; if ($side === self::SIDE_LEFT || $side === self::SIDE_RIGHT) { $add_class = "side_pdus_float"; $float = true; } if (count($found_all_pdus_side)) { echo "
"; if ($float) { echo "
"; } foreach ($found_pdus_side as $current) { $bg_color = $current['bgcolor']; $fg_color = !empty($current['bgcolor']) ? Html::getInvertedColor($current['bgcolor']) : ""; $fg_color_s = "color: $fg_color;"; $picture = false; if ($rel->getFromDB($current['id']) && $pdu->getFromDB($current['pdus_id'])) { $y = $num_u - $current['position']; $height = 1; $model_name = ""; if ($pdu_m->getFromDB($pdu->fields['pdumodels_id'])) { $height = $pdu_m->fields['required_units']; $y = $num_u + 1 - $current['position'] - $height; $picture = $pdu_m->fields['picture_front']; $model_name = $pdu_m->getName(); } $tip = ""; $tip.= " ". $pdu->getTypeName()." ". $pdu->getName()." "; if (!empty($pdu->fields['serial'])) { $tip.= " ". $pdu->fields['serial']." "; } if (!empty($pdu->fields['otherserial'])) { $tip.= " ". $pdu->fields['otherserial']." "; } if (!empty($model_name)) { $tip.= " $model_name "; } $tip.= ""; $picture_c = ""; $item_rand = mt_rand(); if ($picture) { $picture_url = Toolbox::getPictureUrl($picture); $picture_c = 'with_picture'; echo ""; } echo ""; } } if ($float) { echo "
"; echo "
"; // .side_pdus_graph } echo "
"; // .side_pdus $ajax_url = $CFG_GLPI['root_doc']."/ajax/rack.php"; $js = << label) */ static function getSides() { return [ self::SIDE_LEFT => __('Left'), self::SIDE_RIGHT => __('Right'), self::SIDE_TOP => __('Top'), self::SIDE_BOTTOM => __('Bottom'), ]; } /** * Get a side name from its index * @param integer $side See class constants and above `getSides`` method * @return string the side name */ static function getSideName($side) { return self::getSides()[$side]; } /** * Return an iterator for all pdu used in a side of a rack * @param Rack $rack * @param integer $side * @return Iterator */ static function getForRackSide(Rack $rack, $side) { global $DB; return $DB->request([ 'FROM' => self::getTable(), 'WHERE' => [ 'racks_id' => $rack->getID(), 'side' => $side ], 'ORDER' => 'position ASC' ]); } /** * Return an iterator for all used pdu in all racks * * @return Iterator */ static function getUsed() { global $DB; return $DB->request([ 'FROM' => self::getTable() ]); } /** * Return the opposite side from a passed side * @param integer $side * @return integer the oposite side */ static function getOtherSide($side) { switch ($side) { case self::SIDE_TOP; return self::SIDE_BOTTOM; break; case self::SIDE_BOTTOM; return self::SIDE_TOP; break; case self::SIDE_LEFT; return self::SIDE_RIGHT; break; case self::SIDE_RIGHT; return self::SIDE_LEFT; break; } return false; } }