/** * Gets the new path and filename for this view * * @param string $view The view name to get the filename for * @return string */ public function getNewFileName($view) { // Clean up client to mobile for wireless clients $client = $this->client == 'wireless' ? 'mobile' : $this->client; if ($this->deployed) { // Deployed will always use the full key_module name for custom modules $module = $this->getNormalizedModuleName(); $newname = MetaDataFiles::getDeployedFileName($view, $module, $this->type, $client); } else { $newname = MetaDataFiles::getUndeployedFileName($view, $this->module, $this->package, $this->type, $client); } // If this is a history file then add the timestamp back on if ($this->timestamp) { $newname .= '_' . $this->timestamp; } return $newname; }
/** * Converts the legacy Grid metadata to Sidecar style */ public function convertLegacyViewDefsToSidecar() { if (empty($this->legacyViewdefs)) { return; } // If this module is undeployed and doesn't have a base set of metadata, // we should just end things right now. It's not you, it's me. if (!$this->deployed && $this->package) { // This is the marker that decides our fate $found = false; // The undeployed implementation uses history then working, where // working translates to the base file and history translates to // working. $types = array(MB_HISTORYMETADATALOCATION, MB_WORKINGMETADATALOCATION); // Check each type for file existence. This is done similarly to the // implementation, without the overhead of constructing that object // or the parser just yet. foreach ($types as $type) { $file = MetaDataFiles::getUndeployedFileName($this->viewtype, $this->module, $this->package, $type, $this->client); if (file_exists($file)) { $found = true; break; } } // If neither of the files we needed are found, bail now since without // these the upgrade process breaks if (!$found) { $this->logUpgradeStatus("Required {$this->client} {$this->viewtype} metadata for {$this->module} is missing... aborting merge upgrade"); return; } } $this->logUpgradeStatus('Converting ' . $this->client . ' ' . $this->viewtype . ' view defs for ' . $this->module); // Holds merged defs and final defs $newdefs = $tempdefs = $finaldefs = array(); // This needs to be called before the parser is instantiated to prevent // custom metadata from being created from basic module template $defaultDefs = $this->loadDefaultMetadata(); // Get the parser now that default metadata has been fetched $parser = ParserFactory::getParser($this->viewtype, $this->module, $this->package, null, $this->client); // Get the fields that are on the default defs panels since we may need // those as well $defaultDefsFields = $parser->getFieldsFromPanels($defaultDefs['panels']); // Go through merge views, add fields added to detail view to base panel // and fields added to edit view not in detail view or hidden panel $customFields = array(); foreach ($this->legacyViewdefs as $lViewtype => $data) { // We will need a parser no matter what if ($this->sidecar) { $legacyParser = ParserFactory::getParser($lViewtype, $this->module, $this->package, null, $this->client); } else { $legacyParser = ParserFactory::getParser($lViewtype, $this->module, $this->package); } // Step 1, handle tabDef changes $hasTabDefCustomizations = $this->hasTabDefCustomizations($lViewtype); // Tabdefs holds tab def customizations. If there are tab customizations // then the defaultDefs need to be derived from the customize layout // instead of the default viewdef $tabdefs = array(); if ($hasTabDefCustomizations) { // Used for converting tab names. Tabs and panels need to match // and that matching gets handled here and in handleConversion $c = 0; // pull out the tab definitions from the originals, put them into the Canonical Form foreach ($data['templateMeta']['tabDefs'] as $tabName => $tabContent) { // Handle panel labels for matching later $panelNames = $this->getConvertedPanelName($tabName, $c); $tabName = $panelNames['label']; // Save these for later to prevent conflict with new panels later $tabdefs[$tabName] = array('newTab' => $tabContent['newTab'], 'panelDefault' => $tabContent['panelDefault']); // Increment the counter $c++; } // Intermediate step here needed for tabdef customizations... what is // needed is to convert the old panels to new style, then inject the // defaultDef header panel into the newly converted panel set before // continuing on $headerPanel = $defaultDefs['panels'][0]; $defaultDefs = $this->handleConversion($data, 'panels', true); array_unshift($defaultDefs['panels'], $headerPanel); } // TemplateMeta needs to be added if it isn't, to both the default defs // and the parser viewdefs if (isset($data['templateMeta'])) { if (!isset($defaultDefs['templateMeta'])) { $defaultDefs['templateMeta'] = $data['templateMeta']; } else { $defaultDefs['templateMeta'] = array_merge($defaultDefs['templateMeta'], $data['templateMeta']); } if (!isset($parser->_viewdefs['templateMeta'])) { $parser->_viewdefs['templateMeta'] = $defaultDefs['templateMeta']; } else { $parser->_viewdefs['templateMeta'] = array_merge($parser->_viewdefs['templateMeta'], $defaultDefs['templateMeta']); } } // Make a header fields array so that fields that may be in legacy // defs can be plucked out $headerFields = array(); foreach ($defaultDefs['panels'][0]['fields'] as $hField) { // Handle array type fields first if (is_array($hField)) { // But only if there is a name element of the array if (isset($hField['name'])) { // First set from the name of the field we are on $headerFields[$hField['name']] = $hField['name']; // Now if there are fields for this field (fieldset), grab those too if (isset($hField['fields']) && is_array($hField['fields'])) { foreach ($hField['fields'] as $hFieldName) { // Some modules have header field fieldset defs that are arrays if (is_array($hFieldName) && isset($hFieldName['name'])) { $headerFields[$hFieldName['name']] = $hFieldName['name']; } else { $headerFields[$hFieldName] = $hFieldName; } } } } } else { // This will be a string, take it as is $headerFields[$hField] = $hField; } } // Step 2, convert panels if there are any to handle if (!empty($data['panels'])) { // Add spans fields as needed $maxSpan = $parser->getMaxSpan(); // Need to send the entire data array as we need templateData.maxColumns $data = $this->addSpansToFields($data, $maxSpan); $legacyPanelFields = $legacyParser->getFieldsFromPanels($data['panels']); foreach ($legacyPanelFields as $fieldname => $fielddef) { // Handle removal of fields from customFields (legacy defs) as needed $skip = false; if (empty($fieldname) || !$this->isValidField($fieldname)) { // Definitely skip keeping empty and invalid field names. $skip = true; } else { // Is this field already in the customFields collection? $cf = isset($customFields[$fieldname]); // Or perhaps it is explicitly in the removeFields array? $rf = isset($this->removeFields[$fieldname]); // Or maybe it is in the headerFields array? $hf = isset($headerFields[$fieldname]); // If this field is any of the arrays above, skip it if ($cf || $rf || $hf) { $skip = true; } } if ($skip) { continue; } $customFields[$fieldname] = array('data' => $fielddef, 'source' => $lViewtype); } } // Handle field conversion and renames from previous versions $customFields = $this->applyFieldConversionPatches($customFields); // Grab our twitter conversion flag early since twitter_id could be // an array as a field $convertTwitter = $this->needsTwitterConversion(); // Handle unsetting of header fields from non header panels and handle // email1 <=> email conversion foreach ($defaultDefs['panels'] as $panelIndex => $panel) { foreach ($panel['fields'] as $fieldIndex => $fieldName) { // Turn a field name into a string for searching convenience if (is_array($fieldName)) { $lookupFieldName = isset($fieldName['name']) ? $fieldName['name'] : null; } else { $lookupFieldName = $fieldName; } // Handle fields that are not meant to be here, like header // fields, but only if we are not in the header panel if ($panelIndex > 0) { if (isset($lookupFieldName) && isset($headerFields[$lookupFieldName])) { // Remove this field from the defs and move on unset($defaultDefs['panels'][$panelIndex]['fields'][$fieldIndex]); continue; } } // Delete 'team_name' from the layout if module doesn't implement team-security, otherwise leave it; // the field is a part of 'basic' template by default, but module may not implement team-security if (isset($lookupFieldName) && $lookupFieldName == 'team_name' && !$this->isValidField($fieldName)) { unset($defaultDefs['panels'][$panelIndex]['fields'][$fieldIndex]); } // Hack email field into submission if (isset($lookupFieldName) && $lookupFieldName == 'email1') { if (is_array($fieldName)) { $fieldName['name'] = 'email'; $defaultDefs['panels'][$panelIndex]['fields'][$fieldIndex] = $fieldName; } else { $defaultDefs['panels'][$panelIndex]['fields'][$fieldIndex] = 'email'; } } // Handle twitter_id to twitter renaming if (isset($lookupFieldName) && $lookupFieldName == 'twitter_id' && $convertTwitter) { // If twitter is already on the defaults, remove twitter_id entirely, // otherwise rename twitter_id if (isset($defaultDefsFields['twitter'])) { unset($defaultDefs['panels'][$panelIndex]['fields'][$fieldIndex]); } elseif (is_array($fieldName)) { $fieldName['name'] = 'twitter'; $defaultDefs['panels'][$panelIndex]['fields'][$fieldIndex] = $fieldName; } else { $defaultDefs['panels'][$panelIndex]['fields'][$fieldIndex] = 'twitter'; } } } // Reset the array indexes $defaultDefs['panels'][$panelIndex]['fields'] = array_values($defaultDefs['panels'][$panelIndex]['fields']); } // End email1 => email hack // Make sure the array pointer for the panels is back at the start. // This is needed to allow canonical conversion to pick up the right // header panel reset($defaultDefs['panels']); $origFields = array(); // replace viewdefs with defaults, since parser's viewdefs can be already customized by other parts // of the upgrade $parser->_viewdefs['panels'] = $parser->convertFromCanonicalForm($defaultDefs['panels'], $parser->_fielddefs); // get field list $origData = $parser->getFieldsFromPanels($defaultDefs['panels'], $parser->_fielddefs); // Go through existing fields and remove those not in the new data foreach ($origData as $fname => $fielddef) { if (!$this->isValidField($fname)) { continue; } if (is_array($fielddef) && !empty($fielddef['fields'])) { // fieldsets - iterate over each field $setExists = false; if (!empty($customFields[$fielddef['name']])) { $setExists = true; } else { foreach ($fielddef['fields'] as $setfielddef) { if (!is_array($setfielddef)) { $setfname = $setfielddef; } else { // skip weird nameless ones if (empty($setfielddef['name'])) { continue; } $setfname = $setfielddef['name']; } // if we have one field - we take all set if (isset($customFields[$setfname])) { $setExists = true; break; } } } if ($setExists) { $origFields[$fielddef['name']] = $fielddef; // if fields exist, we take all the set as existing fields foreach ($fielddef['fields'] as $setfielddef) { if (!is_array($setfielddef)) { $setfname = $setfielddef; } else { // skip werid nameless ones if (empty($setfielddef['name'])) { continue; } $setfname = $setfielddef['name']; } $origFields[$setfname] = $fielddef; } } else { // else we delete the set but only if it isn't a header field if (!isset($headerFields[$fname])) { $parser->removeField($fname); } } } else { // if it's a regular field, check against existing field in new data if (!isset($customFields[$fname]) && !isset($headerFields[$fname])) { // not there - remove it $parser->removeField($fname); } else { // otherwise - keep as existing $origFields[$fname] = $fielddef; } } } // now go through new fields and add those not in original data // $customFields is legacy defs, $origFields are Sugar7 OOTB defs foreach ($customFields as $fieldname => $data) { if (isset($origFields[$fieldname])) { // If the field is special, massage it into latest format being // sure to maintain its current position in the layout if ($this->isSpecialField($fieldname)) { $fielddata = $this->convertFieldData($fieldname, $data['data']); $this->updateField($parser, $fieldname, $fielddata); } } else { $fielddata = $this->convertFieldData($fieldname, $data['data']); // FIXME: hack since addField cuts field defs if ($this->isSpecialField($fieldname) && empty($parser->_originalViewDef[$fielddata['name']])) { $parser->_originalViewDef[$fielddata['name']] = $fielddata; } $parser->addField($fielddata, $this->getPanelName($parser->_viewdefs['panels'], $data['source'])); } } // Convert the panels array to something useful $panels = $parser->convertToCanonicalForm($parser->_viewdefs['panels'], $parser->_fielddefs); // Add back in tabDefs on the panels if there are any if (!empty($tabdefs)) { foreach ($panels as $key => $panel) { if (!empty($panel['label']) && isset($tabdefs[$panel['label']])) { $panels[$key]['newTab'] = $tabdefs[$panel['label']]['newTab']; $panels[$key]['panelDefault'] = $tabdefs[$panel['label']]['panelDefault']; } } } // There needs to be two different arrays here to allow for non-recursive // but nested array merges. This allows for detail views to be upgraded // first followed by edit views while still maintaining tab definitions // for detail views if (empty($newdefs['panels'])) { $newdefs = $parser->_viewdefs; $newdefs['panels'] = $panels; } else { $tempdefs = $parser->_viewdefs; $tempdefs['panels'] = $panels; } // After all iterations, this will be the final, merged layout def $finaldefs = $this->mergeLayoutDefs($newdefs, $tempdefs); } //Finally re-add any fields that are on the OOB sidecar view but not on the OOB Legacy views $finaldefs = $this->addNewFieldsToLayout($finaldefs); $this->sidecarViewdefs[$this->getNormalizedModuleName()][$this->client]['view'][MetaDataFiles::getName($this->viewtype)] = $finaldefs; }
public function getFileName($view, $moduleName, $packageName, $type = MB_BASEMETADATALOCATION, $client = null) { if ($client === null) { $client = $this->_viewClient; } return MetaDataFiles::getUndeployedFileName($view, $moduleName, $packageName, $type, $client); }