/** * Correct fields defenitions based on \Espo\Custom\Core\Utils\Database\Orm\Fields * * @param array $ormMeta * * @return array */ protected function correctFields($entityName, array $ormMeta) { $entityDefs = $this->getEntityDefs(); $entityMeta = $ormMeta[$entityName]; //load custom field definitions and customCodes foreach ($entityMeta['fields'] as $fieldName => $fieldParams) { if (empty($fieldParams['type'])) { continue; } $fieldType = ucfirst($fieldParams['type']); $className = '\\Espo\\Custom\\Core\\Utils\\Database\\Orm\\Fields\\' . $fieldType; if (!class_exists($className)) { $className = '\\Espo\\Core\\Utils\\Database\\Orm\\Fields\\' . $fieldType; } if (class_exists($className) && method_exists($className, 'load')) { $helperClass = new $className($this->metadata, $ormMeta, $entityDefs); $fieldResult = $helperClass->process($fieldName, $entityName); if (isset($fieldResult['unset'])) { $ormMeta = Util::unsetInArray($ormMeta, $fieldResult['unset']); unset($fieldResult['unset']); } $ormMeta = Util::merge($ormMeta, $fieldResult); } } //todo move to separate file //add a field 'isFollowed' for scopes with 'stream => true' $scopeDefs = $this->getMetadata()->get('scopes.' . $entityName); if (isset($scopeDefs['stream']) && $scopeDefs['stream']) { if (!isset($entityMeta['fields']['isFollowed'])) { $ormMeta[$entityName]['fields']['isFollowed'] = array('type' => 'varchar', 'notStorable' => true); $ormMeta[$entityName]['fields']['followersIds'] = array('type' => 'jsonArray', 'notStorable' => true); $ormMeta[$entityName]['fields']['followersNames'] = array('type' => 'jsonObject', 'notStorable' => true); } } //END: add a field 'isFollowed' for stream => true return $ormMeta; }
public function testUnsetInArrayByString() { $input = array('Account' => array('useCache' => true), 'Contact' => array('useCache' => true)); $unsets = 'Account.useCache'; $result = array('Account' => array(), 'Contact' => array('useCache' => true)); $this->assertEquals($result, Util::unsetInArray($input, $unsets)); }
/** * Unset some element of content data * * @param string | array $path * @param array | string $unsets * @return bool */ public function unsetContents($path, $unsets, $isJSON = true) { $currentData = $this->getContents($path); if ($currentData == false) { $GLOBALS['log']->notice('FileManager::unsetContents: File [' . $this->concatPaths($path) . '] does not exist.'); return false; } $currentDataArray = Utils\Json::getArrayData($currentData); $unsettedData = Utils\Util::unsetInArray($currentDataArray, $unsets, true); if (is_null($unsettedData) || is_array($unsettedData) && empty($unsettedData)) { $fullPath = $this->concatPaths($path); return $this->unlink($fullPath); } if ($isJSON) { return $this->putContentsJson($path, $unsettedData); } return $this->putContents($path, $unsettedData); }
/** * Unset some fields and other stuff in metadat * * @param string $key1 * @param string $key2 * @param array | string $unsets Ex. 'fields.name' * * @return bool */ public function delete($key1, $key2, $unsets) { if (!is_array($unsets)) { $unsets = (array) $unsets; } $normalizedData = array('__APPEND__'); $metaUnsetData = array(); foreach ($unsets as $unsetItem) { $normalizedData[] = $unsetItem; $metaUnsetData[] = implode('.', array($key1, $key2, $unsetItem)); } $unsetData = array($key1 => array($key2 => $normalizedData)); $this->deletedData = Util::merge($this->deletedData, $unsetData); $this->deletedData = Util::unsetInArrayByValue('__APPEND__', $this->deletedData); $this->meta = Util::unsetInArray($this->getData(), $metaUnsetData); }
/** * Unite file content to the file for one directory [NOW ONLY FOR METADATA, NEED TO CHECK FOR LAYOUTS AND OTHERS] * * @param string $dirPath * @param string $type - name of type array("metadata", "layouts"), ex. $this->name * @param bool $recursively - Note: only for first level of sub directory, other levels of sub directories will be ignored * @param string $moduleName - name of module if exists * * @return string - content of the files */ protected function unifySingle($dirPath, $type, $recursively = false, $moduleName = '') { if (empty($dirPath) || !file_exists($dirPath)) { return false; } $unsetFileName = $this->params['unsetFileName']; //get matadata files $fileList = $this->getFileManager()->getFileList($dirPath, $recursively, '\\.json$'); $dirName = $this->getFileManager()->getDirName($dirPath, false); $defaultValues = $this->loadDefaultValues($dirName, $type); $content = array(); $unsets = array(); foreach ($fileList as $dirName => $fileName) { if (is_array($fileName)) { /*get content from files in a sub directory*/ $content[$dirName] = $this->unifySingle(Utils\Util::concatPath($dirPath, $dirName), $type, false, $moduleName); //only first level of a sub directory } else { /*get content from a single file*/ if ($fileName == $unsetFileName) { $fileContent = $this->getFileManager()->getContents(array($dirPath, $fileName)); $unsets = Utils\Json::getArrayData($fileContent); continue; } /*END: Save data from unset.json*/ $mergedValues = $this->unifyGetContents(array($dirPath, $fileName), $defaultValues); if (!empty($mergedValues)) { $name = $this->getFileManager()->getFileName($fileName, '.json'); $content[$name] = $mergedValues; } } } //unset content $content = Utils\Util::unsetInArray($content, $unsets); //END: unset content return $content; }
/** * Schema convertation process * * @param array $ormMeta * @param array|null $entityList * * @return \Doctrine\DBAL\Schema\Schema */ public function process(array $ormMeta, $entityList = null) { $GLOBALS['log']->debug('Schema\\Converter - Start: building schema'); //check if exist files in "Tables" directory and merge with ormMetadata $ormMeta = Util::merge($ormMeta, $this->getCustomTables($ormMeta)); //unset some keys in orm if (isset($ormMeta['unset'])) { $ormMeta = Util::unsetInArray($ormMeta, $ormMeta['unset']); unset($ormMeta['unset']); } //END: unset some keys in orm if (isset($entityList)) { $entityList = is_string($entityList) ? (array) $entityList : $entityList; $dependentEntities = $this->getDependentEntities($entityList, $ormMeta); $GLOBALS['log']->debug('Rebuild Database for entities: [' . implode(', ', $entityList) . '] with dependent entities: [' . implode(', ', $dependentEntities) . ']'); $ormMeta = array_intersect_key($ormMeta, array_flip($dependentEntities)); } $schema = $this->getSchema(true); $tables = array(); foreach ($ormMeta as $entityName => $entityParams) { $tableName = Util::toUnderScore($entityName); if ($schema->hasTable($tableName)) { if (!isset($tables[$entityName])) { $tables[$entityName] = $schema->getTable($tableName); } $GLOBALS['log']->debug('DBAL: Table [' . $tableName . '] exists.'); continue; } $tables[$entityName] = $schema->createTable($tableName); $primaryColumns = array(); $uniqueColumns = array(); $indexList = array(); //list of indexes like array( array(comlumn1, column2), array(column3)) foreach ($entityParams['fields'] as $fieldName => $fieldParams) { if (isset($fieldParams['notStorable']) && $fieldParams['notStorable'] || in_array($fieldParams['type'], $this->notStorableTypes)) { continue; } switch ($fieldParams['type']) { case 'id': $primaryColumns[] = Util::toUnderScore($fieldName); break; } $fieldType = isset($fieldParams['dbType']) ? $fieldParams['dbType'] : $fieldParams['type']; $fieldType = strtolower($fieldType); /** doctrine uses strtolower for all field types */ if (!in_array($fieldType, $this->typeList)) { $GLOBALS['log']->debug('Converters\\Schema::process(): Field type [' . $fieldType . '] does not exist ' . $entityName . ':' . $fieldName); continue; } $columnName = Util::toUnderScore($fieldName); if (!$tables[$entityName]->hasColumn($columnName)) { $tables[$entityName]->addColumn($columnName, $fieldType, $this->getDbFieldParams($fieldParams)); } //add unique if ($fieldParams['type'] != 'id' && isset($fieldParams['unique'])) { $uniqueColumns = $this->getKeyList($columnName, $fieldParams['unique'], $uniqueColumns); } //END: add unique //add index. It can be defined in entityDefs as "index" if (isset($fieldParams['index'])) { $indexList = $this->getKeyList($columnName, $fieldParams['index'], $indexList); } //END: add index } $tables[$entityName]->setPrimaryKey($primaryColumns); //add indexes if (isset($entityParams['indexes']) && is_array($entityParams['indexes'])) { foreach ($entityParams['indexes'] as $indexName => $indexParams) { if (is_array($indexParams['columns'])) { $tableIndexName = $this->generateIndexName($indexName, $entityName); $indexList[$tableIndexName] = Util::toUnderScore($indexParams['columns']); } } } if (!empty($indexList)) { foreach ($indexList as $indexName => $indexItem) { $tableIndexName = is_string($indexName) ? $indexName : null; $tables[$entityName]->addIndex($indexItem, $tableIndexName); } } if (!empty($uniqueColumns)) { foreach ($uniqueColumns as $uniqueItem) { $tables[$entityName]->addUniqueIndex($uniqueItem); } } } //check and create columns/tables for relations foreach ($ormMeta as $entityName => $entityParams) { if (!isset($entityParams['relations'])) { continue; } foreach ($entityParams['relations'] as $relationName => $relationParams) { switch ($relationParams['type']) { case 'manyMany': $tableName = $relationParams['relationName']; //check for duplication tables if (!isset($tables[$tableName])) { //no needs to create the table if it already exists $tables[$tableName] = $this->prepareManyMany($entityName, $relationParams, $tables); } break; case 'belongsTo': $columnName = Util::toUnderScore($relationParams['key']); $tables[$entityName]->addIndex(array($columnName)); break; } } } //END: check and create columns/tables for relations $GLOBALS['log']->debug('Schema\\Converter - End: building schema'); return $schema; }
public function afterProcess(array $ormMeta) { $entityDefs = $this->getEntityDefs(); //load custom field definitions and customCodes foreach ($ormMeta as $entityName => &$entityParams) { foreach ($entityParams['fields'] as $fieldName => $fieldParams) { //load custom field definitions $fieldType = ucfirst($fieldParams['type']); $className = '\\Espo\\Custom\\Core\\Utils\\Database\\Orm\\Fields\\' . $fieldType; if (!class_exists($className)) { $className = '\\Espo\\Core\\Utils\\Database\\Orm\\Fields\\' . $fieldType; } if (class_exists($className) && method_exists($className, 'load')) { $helperClass = new $className($this->metadata, $ormMeta, $entityDefs); $fieldResult = $helperClass->process($fieldName, $entityName); if (isset($fieldResult['unset'])) { $ormMeta = Util::unsetInArray($ormMeta, $fieldResult['unset']); unset($fieldResult['unset']); } $ormMeta = Util::merge($ormMeta, $fieldResult); } //END: load custom field definitions //todo move to separate file //add a field 'isFollowed' for scopes with 'stream => true' $scopeDefs = $this->getMetadata()->get('scopes.' . $entityName); if (isset($scopeDefs['stream']) && $scopeDefs['stream']) { if (!isset($entityParams['fields']['isFollowed'])) { $entityParams['fields']['isFollowed'] = array('type' => 'varchar', 'notStorable' => true); } } //END: add a field 'isFollowed' for stream => true } } foreach ($ormMeta as $entityName => &$entityParams) { foreach ($entityParams['fields'] as $fieldName => &$fieldParams) { switch ($fieldParams['type']) { case 'id': if ($fieldParams['dbType'] != 'int') { $fieldParams = array_merge($fieldParams, $this->idParams); } break; case 'foreignId': $fieldParams = array_merge($fieldParams, $this->idParams); $fieldParams['notNull'] = false; break; case 'foreignType': $fieldParams['dbType'] = Entity::VARCHAR; $fieldParams['len'] = $this->defaultLength['varchar']; break; case 'bool': $fieldParams['default'] = isset($fieldParams['default']) ? (bool) $fieldParams['default'] : $this->defaultValue['bool']; break; } } } return $ormMeta; }