metadata = $metadata; $this->language = $language; $this->metadataUtils = new \Espo\Core\Utils\Metadata\Utils($this->metadata); } protected function getMetadata() { return $this->metadata; } protected function getLanguage() { return $this->language; } protected function getMetadataUtils() { return $this->metadataUtils; } public function read($name, $scope) { $fieldDef = $this->getFieldDef($name, $scope); $fieldDef['label'] = $this->getLanguage()->translate($name, 'fields', $scope); return $fieldDef; } public function create($name, $fieldDef, $scope) { $existingField = $this->getFieldDef($name, $scope); if (isset($existingField)) { throw new Conflict('Field ['.$name.'] exists in '.$scope); } return $this->update($name, $fieldDef, $scope); } public function update($name, $fieldDef, $scope) { /*Add option to metadata to identify the custom field*/ if (!$this->isCore($name, $scope)) { $fieldDef[$this->customOptionName] = true; } $res = true; if (isset($fieldDef['label'])) { $this->setLabel($name, $fieldDef['label'], $scope); } if (isset($fieldDef['type']) && $fieldDef['type'] == 'enum') { if (isset($fieldDef['translatedOptions'])) { $this->setTranslatedOptions($name, $fieldDef['translatedOptions'], $scope); } } if (isset($fieldDef['label']) || isset($fieldDef['translatedOptions'])) { $res &= $this->getLanguage()->save(); } if ($this->isDefsChanged($name, $fieldDef, $scope)) { $res &= $this->setEntityDefs($name, $fieldDef, $scope); } return (bool) $res; } public function delete($name, $scope) { if ($this->isCore($name, $scope)) { throw new Error('Cannot delete core field ['.$name.'] in '.$scope); } $unsets = array( 'fields.'.$name, 'links.'.$name, ); $this->getMetadata()->delete($this->metadataType, $scope, $unsets); $res = $this->getMetadata()->save(); $res &= $this->deleteLabel($name, $scope); return (bool) $res; } protected function setEntityDefs($name, $fieldDef, $scope) { $fieldDef = $this->normalizeDefs($name, $fieldDef, $scope); $this->getMetadata()->set($this->metadataType, $scope, $fieldDef); $res = $this->getMetadata()->save(); return $res; } protected function setTranslatedOptions($name, $value, $scope) { return $this->getLanguage()->set($scope, 'options', $name, $value); } protected function setLabel($name, $value, $scope) { return $this->getLanguage()->set($scope, 'fields', $name, $value); } protected function deleteLabel($name, $scope) { $this->getLanguage()->delete($scope, 'fields', $name); $this->getLanguage()->delete($scope, 'options', $name); return $this->getLanguage()->save(); } protected function getFieldDef($name, $scope) { return $this->getMetadata()->get($this->metadataType.'.'.$scope.'.fields.'.$name); } protected function getLinkDef($name, $scope) { return $this->getMetadata()->get($this->metadataType.'.'.$scope.'.links.'.$name); } /** * Prepare input fieldDefs, remove unnecessary fields * * @param string $fieldName * @param array $fieldDef * @param string $scope * @return array */ protected function prepareFieldDef($name, $fieldDef, $scope) { $unnecessaryFields = array( 'name', 'label', 'translatedOptions', ); foreach ($unnecessaryFields as $fieldName) { if (isset($fieldDef[$fieldName])) { unset($fieldDef[$fieldName]); } } if (isset($fieldDef['linkDefs'])) { $linkDefs = $fieldDef['linkDefs']; unset($fieldDef['linkDefs']); } $currentOptionList = array_keys((array) $this->getFieldDef($name, $scope)); foreach ($fieldDef as $defName => $defValue) { if ( (!isset($defValue) || $defValue === '') && !in_array($defName, $currentOptionList) ) { unset($fieldDef[$defName]); } } return $fieldDef; } /** * Add all needed block for a field defenition * * @param string $fieldName * @param array $fieldDef * @param string $scope * @return array */ protected function normalizeDefs($fieldName, array $fieldDef, $scope) { $fieldDef = $this->prepareFieldDef($fieldName, $fieldDef, $scope); $metaFieldDef = $this->getMetadataUtils()->getFieldDefsInFieldMeta($fieldDef); if (isset($metaFieldDef)) { $fieldDef = Util::merge($metaFieldDef, $fieldDef); } $defs = array( 'fields' => array( $fieldName => $fieldDef, ), ); /** Save links for a field. */ $metaLinkDef = $this->getMetadataUtils()->getLinkDefsInFieldMeta($scope, $fieldDef); if (isset($linkDefs) || isset($metaLinkDef)) { $linkDefs = Util::merge((array) $metaLinkDef, (array) $linkDefs); $defs['links'] = array( $fieldName => $linkDefs, ); } return $defs; } /** * Check if changed metadata defenition for a field except 'label' * * @return boolean */ protected function isDefsChanged($name, $fieldDef, $scope) { $fieldDef = $this->prepareFieldDef($name, $fieldDef, $scope); $currentFieldDef = $this->getFieldDef($name, $scope); $this->isChanged = Util::isEquals($fieldDef, $currentFieldDef) ? false : true; return $this->isChanged; } /** * Only for update method * * @return boolean */ public function isChanged() { return $this->isChanged; } /** * Check if a field is core field * * @param string $name * @param string $scope * @return boolean */ protected function isCore($name, $scope) { $existingField = $this->getFieldDef($name, $scope); if (isset($existingField) && (!isset($existingField[$this->customOptionName]) || !$existingField[$this->customOptionName])) { return true; } return false; } }