/**
     * Display a form for modifying several objects at once
     * The form will be submitted to the current page, with the specified additional values	 
     */
    public static function DisplayBulkModifyForm($oP, $sClass, $aSelectedObj, $sCustomOperation, $sCancelUrl, $aExcludeAttributes = array(), $aContextData = array())
    {
        if (count($aSelectedObj) > 0) {
            $iAllowedCount = count($aSelectedObj);
            $sSelectedObj = implode(',', $aSelectedObj);
            $sOQL = "SELECT {$sClass} WHERE id IN (" . $sSelectedObj . ")";
            $oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL));
            // Compute the distribution of the values for each field to determine which of the "scalar" fields are homogenous
            $aList = MetaModel::ListAttributeDefs($sClass);
            $aValues = array();
            foreach ($aList as $sAttCode => $oAttDef) {
                if ($oAttDef->IsScalar()) {
                    $aValues[$sAttCode] = array();
                }
            }
            while ($oObj = $oSet->Fetch()) {
                foreach ($aList as $sAttCode => $oAttDef) {
                    if ($oAttDef->IsScalar() && $oAttDef->IsWritable()) {
                        $currValue = $oObj->Get($sAttCode);
                        if ($oAttDef instanceof AttributeCaseLog) {
                            $currValue = ' ';
                            // Don't put an empty string, in case the field would be considered as mandatory...
                        }
                        if (is_object($currValue)) {
                            continue;
                        }
                        // Skip non scalar values...
                        if (!array_key_exists($currValue, $aValues[$sAttCode])) {
                            $aValues[$sAttCode][$currValue] = array('count' => 1, 'display' => $oObj->GetAsHTML($sAttCode));
                        } else {
                            $aValues[$sAttCode][$currValue]['count']++;
                        }
                    }
                }
            }
            // Now create an object that has values for the homogenous values only
            $oDummyObj = new $sClass();
            // @@ What if the class is abstract ?
            $aComments = array();
            function MyComparison($a, $b)
            {
                if ($a['count'] == $b['count']) {
                    return 0;
                }
                return $a['count'] > $b['count'] ? -1 : 1;
            }
            $iFormId = cmdbAbstractObject::GetNextFormId();
            // Identifier that prefixes all the form fields
            $sReadyScript = '';
            $aDependsOn = array();
            $sFormPrefix = '2_';
            foreach ($aList as $sAttCode => $oAttDef) {
                $aPrerequisites = MetaModel::GetPrerequisiteAttributes($sClass, $sAttCode);
                // List of attributes that are needed for the current one
                if (count($aPrerequisites) > 0) {
                    // When 'enabling' a field, all its prerequisites must be enabled too
                    $sFieldList = "['{$sFormPrefix}" . implode("','{$sFormPrefix}", $aPrerequisites) . "']";
                    $oP->add_ready_script("\$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, {$sFieldList}, true); } );\n");
                }
                $aDependents = MetaModel::GetDependentAttributes($sClass, $sAttCode);
                // List of attributes that are needed for the current one
                if (count($aDependents) > 0) {
                    // When 'disabling' a field, all its dependent fields must be disabled too
                    $sFieldList = "['{$sFormPrefix}" . implode("','{$sFormPrefix}", $aDependents) . "']";
                    $oP->add_ready_script("\$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, {$sFieldList}, false); } );\n");
                }
                if ($oAttDef->IsScalar() && $oAttDef->IsWritable()) {
                    if ($oAttDef->GetEditClass() == 'One Way Password') {
                        $sTip = "Unknown values";
                        $sReadyScript .= "\$('#multi_values_{$sAttCode}').qtip( { content: '{$sTip}', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
                        $oDummyObj->Set($sAttCode, null);
                        $aComments[$sAttCode] = '<input type="checkbox" id="enable_' . $iFormId . '_' . $sAttCode . '" onClick="ToogleField(this.checked, \'' . $iFormId . '_' . $sAttCode . '\')"/>';
                        $aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_' . $sAttCode . '"> ? </div>';
                        $sReadyScript .= 'ToogleField(false, \'' . $iFormId . '_' . $sAttCode . '\');' . "\n";
                    } else {
                        $iCount = count($aValues[$sAttCode]);
                        if ($iCount == 1) {
                            // Homogenous value
                            reset($aValues[$sAttCode]);
                            $aKeys = array_keys($aValues[$sAttCode]);
                            $currValue = $aKeys[0];
                            // The only value is the first key
                            //echo "<p>current value for $sAttCode : $currValue</p>";
                            $oDummyObj->Set($sAttCode, $currValue);
                            $aComments[$sAttCode] = '';
                            if ($sAttCode != MetaModel::GetStateAttributeCode($sClass)) {
                                $aComments[$sAttCode] .= '<input type="checkbox" checked id="enable_' . $iFormId . '_' . $sAttCode . '"  onClick="ToogleField(this.checked, \'' . $iFormId . '_' . $sAttCode . '\')"/>';
                            }
                            $aComments[$sAttCode] .= '<div class="mono_value">1</div>';
                        } else {
                            // Non-homogenous value
                            $aMultiValues = $aValues[$sAttCode];
                            uasort($aMultiValues, 'MyComparison');
                            $iMaxCount = 5;
                            $sTip = "<p><b>" . Dict::Format('UI:BulkModify_Count_DistinctValues', $iCount) . "</b><ul>";
                            $index = 0;
                            foreach ($aMultiValues as $sCurrValue => $aVal) {
                                $sDisplayValue = empty($aVal['display']) ? '<i>' . Dict::S('Enum:Undefined') . '</i>' : str_replace(array("\n", "\r"), " ", $aVal['display']);
                                $sTip .= "<li>" . Dict::Format('UI:BulkModify:Value_Exists_N_Times', $sDisplayValue, $aVal['count']) . "</li>";
                                $index++;
                                if ($iMaxCount == $index) {
                                    $sTip .= "<li>" . Dict::Format('UI:BulkModify:N_MoreValues', count($aMultiValues) - $iMaxCount) . "</li>";
                                    break;
                                }
                            }
                            $sTip .= "</ul></p>";
                            $sTip = addslashes($sTip);
                            $sReadyScript .= "\$('#multi_values_{$sAttCode}').qtip( { content: '{$sTip}', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
                            $oDummyObj->Set($sAttCode, null);
                            $aComments[$sAttCode] = '';
                            if ($sAttCode != MetaModel::GetStateAttributeCode($sClass)) {
                                $aComments[$sAttCode] .= '<input type="checkbox" id="enable_' . $iFormId . '_' . $sAttCode . '" onClick="ToogleField(this.checked, \'' . $iFormId . '_' . $sAttCode . '\')"/>';
                            }
                            $aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_' . $sAttCode . '">' . $iCount . '</div>';
                        }
                        $sReadyScript .= 'ToogleField(' . ($iCount == 1 ? 'true' : 'false') . ', \'' . $iFormId . '_' . $sAttCode . '\');' . "\n";
                    }
                }
            }
            $sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
            if ($sStateAttCode != '' && $oDummyObj->GetState() == '') {
                // Hmmm, it's not gonna work like this ! Set a default value for the "state"
                // Maybe we should use the "state" that is the most common among the objects...
                $aMultiValues = $aValues[$sStateAttCode];
                uasort($aMultiValues, 'MyComparison');
                foreach ($aMultiValues as $sCurrValue => $aVal) {
                    $oDummyObj->Set($sStateAttCode, $sCurrValue);
                    break;
                }
                //$oStateAtt = MetaModel::GetAttributeDef($sClass, $sStateAttCode);
                //$oDummyObj->Set($sStateAttCode, $oStateAtt->GetDefaultValue());
            }
            $oP->add("<div class=\"page_header\">\n");
            $oP->add("<h1>" . $oDummyObj->GetIcon() . "&nbsp;" . Dict::Format('UI:Modify_M_ObjectsOf_Class_OutOf_N', $iAllowedCount, $sClass, $iAllowedCount) . "</h1>\n");
            $oP->add("</div>\n");
            $oP->add("<div class=\"wizContainer\">\n");
            $sDisableFields = json_encode($aExcludeAttributes);
            $aParams = array('fieldsComments' => $aComments, 'noRelations' => true, 'custom_operation' => $sCustomOperation, 'custom_button' => Dict::S('UI:Button:PreviewModifications'), 'selectObj' => $sSelectedObj, 'preview_mode' => true, 'disabled_fields' => $sDisableFields, 'disable_plugins' => true);
            $aParams = $aParams + $aContextData;
            // merge keeping associations
            $oDummyObj->DisplayModifyForm($oP, $aParams);
            $oP->add("</div>\n");
            $oP->add_ready_script($sReadyScript);
            $oP->add_ready_script(<<<EOF
\$('.wizContainer button.cancel').unbind('click');
\$('.wizContainer button.cancel').click( function() { window.location.href = '{$sCancelUrl}'; } );
EOF
);
        } else {
            $oP->p("No object selected !, nothing to do");
        }
    }
Beispiel #2
0
 /**
  * Builds an object that contains the values that are common to all the objects
  * in the set. If for a given attribute, objects in the set have various values
  * then the resulting object will contain null for this value.
  * @param $aValues Hash Output: the distribution of the values, in the set, for each attribute
  * @return DBObject The object with the common values
  */
 public function ComputeCommonObject(&$aValues)
 {
     $sClass = $this->GetClass();
     $aList = MetaModel::ListAttributeDefs($sClass);
     $aValues = array();
     foreach ($aList as $sAttCode => $oAttDef) {
         if ($oAttDef->IsScalar()) {
             $aValues[$sAttCode] = array();
         }
     }
     $this->Rewind();
     while ($oObj = $this->Fetch()) {
         foreach ($aList as $sAttCode => $oAttDef) {
             if ($oAttDef->IsScalar() && $oAttDef->IsWritable()) {
                 $currValue = $oObj->Get($sAttCode);
                 if (is_object($currValue)) {
                     continue;
                 }
                 // Skip non scalar values...
                 if (!array_key_exists($currValue, $aValues[$sAttCode])) {
                     $aValues[$sAttCode][$currValue] = array('count' => 1, 'display' => $oObj->GetAsHTML($sAttCode));
                 } else {
                     $aValues[$sAttCode][$currValue]['count']++;
                 }
             }
         }
     }
     foreach ($aValues as $sAttCode => $aMultiValues) {
         if (count($aMultiValues) > 1) {
             uasort($aValues[$sAttCode], 'HashCountComparison');
         }
     }
     // Now create an object that has values for the homogenous values only
     $oCommonObj = new $sClass();
     // @@ What if the class is abstract ?
     $aComments = array();
     $iFormId = cmdbAbstractObject::GetNextFormId();
     // Identifier that prefixes all the form fields
     $sReadyScript = '';
     $aDependsOn = array();
     $sFormPrefix = '2_';
     foreach ($aList as $sAttCode => $oAttDef) {
         if ($oAttDef->IsScalar() && $oAttDef->IsWritable()) {
             if ($oAttDef->GetEditClass() == 'One Way Password') {
                 $oCommonObj->Set($sAttCode, null);
             } else {
                 $iCount = count($aValues[$sAttCode]);
                 if ($iCount == 1) {
                     // Homogenous value
                     reset($aValues[$sAttCode]);
                     $aKeys = array_keys($aValues[$sAttCode]);
                     $currValue = $aKeys[0];
                     // The only value is the first key
                     $oCommonObj->Set($sAttCode, $currValue);
                 } else {
                     // Non-homogenous value
                     $oCommonObj->Set($sAttCode, null);
                 }
             }
         }
     }
     $this->Rewind();
     return $oCommonObj;
 }