/**
  * Returns a list of HTML fragments implementing all bundles in an HTML form for the specified screen
  * $pm_screen can be a screen tag (eg. "Screen5") or a screen_id (eg. 5) 
  *
  * @param mixed $pm_screen screen_id or code in default UI to return bundles for
  * @param array $pa_options Array of options. Supports and option getBundleFormHTML() supports plus:
  *		request = the current request object; used to apply user privs to bundle generation
  *		force = list of bundles to force onto form if they are not included in the UI; forced bundles will be included at the bottom of the form
  *		forceHidden = list of *intrinsic* fields to force onto form as hidden <input> elements if they are not included in the UI; NOTE: only intrinsic fields may be specified
  *		omit = list of bundles to omit from form in the event they are included in the UI
  *		restrictToTypes = 
  *	@return array List of bundle HTML to display in form, keyed on placement code
  */
 public function getBundleFormHTMLForScreen($pm_screen, $pa_options, &$pa_placements = null)
 {
     $va_omit_bundles = isset($pa_options['omit']) && is_array($pa_options['omit']) ? $pa_options['omit'] : array();
     $vs_table_name = $this->tableName();
     if (isset($pa_options['ui_instance']) && $pa_options['ui_instance']) {
         $t_ui = $pa_options['ui_instance'];
     } else {
         $t_ui = ca_editor_uis::loadDefaultUI($vs_table_name, $pa_options['request'], $this->getTypeID());
     }
     if (!$t_ui) {
         return false;
     }
     if (($vn_ui_access = ca_editor_uis::getAccessForUI($pa_options['request'], $t_ui->getPrimaryKey())) === __CA_BUNDLE_ACCESS_NONE__) {
         // no access to UI
         $this->postError(2320, _t('Access denied to UI %1', $t_ui->get('editor_code')), "BundlableLabelableBaseModelWithAttributes->getBundleFormHTMLForScreen()");
         return false;
     }
     if (($vn_screen_access = ca_editor_uis::getAccessForScreen($pa_options['request'], $pm_screen)) === __CA_BUNDLE_ACCESS_NONE__) {
         // no access to screen
         $this->postError(2320, _t('Access denied to screen %1', $pm_screen), "BundlableLabelableBaseModelWithAttributes->getBundleFormHTMLForScreen()");
         return false;
     }
     if (isset($pa_options['bundles']) && is_array($pa_options['bundles'])) {
         $va_bundles = $pa_options['bundles'];
     } else {
         $va_bundles = $t_ui->getScreenBundlePlacements($pm_screen);
     }
     $vs_form_name = caGetOption('formName', $pa_options, '');
     $va_bundle_html = array();
     $vn_pk_id = $this->getPrimaryKey();
     $va_bundles_present = array();
     if (is_array($va_bundles)) {
         $o_dm = $this->getAppDatamodel();
         $va_definition_bundle_names = array();
         foreach ($va_bundles as $va_bundle) {
             if ($va_bundle['bundle_name'] === $vs_type_id_fld) {
                 continue;
             }
             // skip type_id
             if (!$vn_pk_id && $va_bundle['bundle_name'] === $vs_hier_parent_id_fld) {
                 continue;
             }
             if (in_array($va_bundle['bundle_name'], $va_omit_bundles)) {
                 continue;
             }
             $va_definition_bundle_names[(!$o_dm->tableExists($va_bundle['bundle_name']) ? "{$vs_table_name}." : "") . str_replace("ca_attribute_", "", $va_bundle['bundle_name'])] = 1;
         }
         ca_metadata_dictionary_entries::preloadDefinitions(array_keys($va_definition_bundle_names));
         if (is_subclass_of($this, 'BaseRelationshipModel')) {
             $vs_type_id_fld = $this->getTypeFieldName();
             if (isset($pa_options['restrictToTypes']) && is_array($pa_options['restrictToTypes'])) {
                 $va_valid_element_codes = $this->getApplicableElementCodesForTypes(caMakeRelationshipTypeIDList($vs_table_name, $pa_options['restrictToTypes']));
             } else {
                 $va_valid_element_codes = null;
             }
         } else {
             $vs_type_id_fld = isset($this->ATTRIBUTE_TYPE_ID_FLD) ? $this->ATTRIBUTE_TYPE_ID_FLD : null;
             $vs_hier_parent_id_fld = isset($this->HIERARCHY_PARENT_ID_FLD) ? $this->HIERARCHY_PARENT_ID_FLD : null;
             if (isset($pa_options['restrictToTypes']) && is_array($pa_options['restrictToTypes'])) {
                 $va_valid_element_codes = $this->getApplicableElementCodesForTypes(caMakeTypeIDList($vs_table_name, $pa_options['restrictToTypes']));
             } else {
                 $va_valid_element_codes = null;
             }
         }
         $vn_c = 0;
         foreach ($va_bundles as $va_bundle) {
             if ($va_bundle['bundle_name'] === $vs_type_id_fld) {
                 continue;
             }
             // skip type_id
             if (!$vn_pk_id && $va_bundle['bundle_name'] === $vs_hier_parent_id_fld) {
                 continue;
             }
             if (in_array($va_bundle['bundle_name'], $va_omit_bundles)) {
                 continue;
             }
             if ($va_valid_element_codes && substr($va_bundle['bundle_name'], 0, 13) == 'ca_attribute_') {
                 if (!in_array(substr($va_bundle['bundle_name'], 13), $va_valid_element_codes)) {
                     continue;
                 }
             }
             // Test for user action restrictions on intrinsic fields
             $vb_output_bundle = true;
             if ($this->hasField($va_bundle['bundle_name'])) {
                 if (is_array($va_requires = $this->getFieldInfo($va_bundle['bundle_name'], 'REQUIRES'))) {
                     foreach ($va_requires as $vs_required_action) {
                         if (!$pa_options['request']->user->canDoAction($vs_required_action)) {
                             $vb_output_bundle = false;
                             break;
                         }
                     }
                 }
             }
             if (!$vb_output_bundle) {
                 continue;
             }
             if ($vn_screen_access === __CA_BUNDLE_ACCESS_READONLY__) {
                 $va_bundle['settings']['readonly'] = true;
                 // force all bundles to read-only when user has "Read" access to screen
             } elseif ($vn_screen_access !== __CA_BUNDLE_ACCESS_EDIT__) {
                 // no edit access so bail
                 //$this->postError(2320, _t('Access denied to screen %1', $pm_screen), "BundlableLabelableBaseModelWithAttributes->getBundleFormHTMLForScreen()");
                 continue;
             }
             $va_bundle['settings']['placement_id'] = $va_bundle['placement_id'];
             if ($vs_bundle_form_html = $this->getBundleFormHTML($va_bundle['bundle_name'], 'P' . $va_bundle['placement_id'], $va_bundle['settings'], $pa_options, $vs_bundle_display_name)) {
                 $va_bundle_html[$va_bundle['placement_code']] = "<a name=\"{$pm_screen}_{$va_bundle['placement_id']}\"></a>{$vs_bundle_form_html}";
                 $va_bundles_present[$va_bundle['bundle_name']] = true;
                 $pa_placements["{$pm_screen}_{$va_bundle['placement_id']}"] = array('name' => $vs_bundle_display_name ? $vs_bundle_display_name : $this->getDisplayLabel($vs_table_name . "." . $va_bundle['bundle_name']), 'placement_id' => $va_bundle['placement_id'], 'bundle' => $va_bundle['bundle_name'], 'id' => 'P' . $va_bundle['placement_id'] . caGetOption('formName', $pa_options, ''));
             }
         }
     }
     // is this a form to create a new item?
     if (!$vn_pk_id) {
         // auto-add mandatory fields if this is a new object
         $va_mandatory_fields = $this->getMandatoryFields();
         foreach ($va_mandatory_fields as $vs_field) {
             if (!isset($va_bundles_present[$vs_field]) || !$va_bundles_present[$vs_field]) {
                 $va_bundle_html[$vs_field] = $this->getBundleFormHTML($vs_field, 'mandatory_' . $vs_field, array(), $pa_options);
             }
         }
         // add type_id
         if (isset($this->ATTRIBUTE_TYPE_ID_FLD) && $this->ATTRIBUTE_TYPE_ID_FLD && !in_array('type_id', $va_omit_bundles)) {
             $va_bundle_html[$this->ATTRIBUTE_TYPE_ID_FLD] = caHTMLHiddenInput($this->ATTRIBUTE_TYPE_ID_FLD, array('value' => $pa_options['request']->getParameter($this->ATTRIBUTE_TYPE_ID_FLD, pString)));
         }
         // add parent_id
         if (isset($this->HIERARCHY_PARENT_ID_FLD) && $this->HIERARCHY_PARENT_ID_FLD && !in_array('parent_id', $va_omit_bundles)) {
             $va_bundle_html[$this->HIERARCHY_PARENT_ID_FLD] = caHTMLHiddenInput($this->HIERARCHY_PARENT_ID_FLD, array('value' => $pa_options['request']->getParameter($this->HIERARCHY_PARENT_ID_FLD, pInteger)));
         }
         // add forced bundles
         if (isset($pa_options['force']) && $pa_options['force']) {
             if (!is_array($pa_options['force'])) {
                 $pa_options['force'] = array($pa_options['force']);
             }
             foreach ($pa_options['force'] as $vn_x => $vs_bundle) {
                 if (!isset($va_bundles_present[$vs_bundle]) || !$va_bundles_present[$vs_bundle]) {
                     $va_bundle_html['_force_' . $vs_bundle] = $this->getBundleFormHTML($vs_bundle, 'force_' . $vs_field, array(), $pa_options);
                 }
             }
         }
         // add forced hidden intrinsic fields
         if (isset($pa_options['forceHidden']) && $pa_options['forceHidden']) {
             if (!is_array($pa_options['forceHidden'])) {
                 $pa_options['forceHidden'] = array($pa_options['forceHidden']);
             }
             foreach ($pa_options['forceHidden'] as $vn_x => $vs_field) {
                 if (!isset($va_bundles_present[$vs_field]) || !$va_bundles_present[$vs_field]) {
                     $va_bundle_html['_force_hidden_' . $vs_field] = caHTMLHiddenInput($vs_field, array('value' => $pa_options['request']->getParameter($vs_field, pString)));
                 }
             }
         }
     }
     return $va_bundle_html;
 }