custom modules support

This commit is contained in:
Yuri Kuznetsov
2021-07-02 12:11:33 +03:00
parent d95d562843
commit 29398de678
9 changed files with 124 additions and 52 deletions
+4
View File
@@ -106,6 +106,10 @@ module.exports = grunt => {
'!build/tmp/custom/Espo/Modules/.htaccess',
'build/tmp/install/config.php',
'build/tmp/vendor/*/*/.git',
'build/tmp/custom/Espo/Custom/*',
'build/tmp/client/custom/*',
'!build/tmp/client/custom/modules',
'build/tmp/client/custom/modules/*',
]
}
},
+19 -1
View File
@@ -41,6 +41,7 @@ use Espo\Core\{
HookManager,
Utils\Database\Schema\SchemaProxy,
Utils\Log,
Utils\Module,
};
use Throwable;
@@ -68,6 +69,8 @@ class DataManager
private $log;
private $module;
private $cachePath = 'data/cache';
public function __construct(
@@ -79,7 +82,8 @@ class DataManager
OrmMetadataData $ormMetadataData,
HookManager $hookManager,
SchemaProxy $schemaProxy,
Log $log
Log $log,
Module $module
) {
$this->entityManager = $entityManager;
$this->config = $config;
@@ -90,6 +94,7 @@ class DataManager
$this->hookManager = $hookManager;
$this->schemaProxy = $schemaProxy;
$this->log = $log;
$this->module = $module;
}
/**
@@ -99,6 +104,7 @@ class DataManager
{
$this->clearCache();
$this->disableHooks();
$this->checkModules();
$this->populateConfigParameters();
$this->rebuildMetadata();
$this->rebuildDatabase($entityList);
@@ -329,4 +335,16 @@ class DataManager
{
$this->hookManager->enable();
}
private function checkModules(): void
{
$moduleNameList = $this->module->getList();
if (count(array_unique($moduleNameList)) !== count($moduleNameList)) {
throw new Error(
"There is a same module in both `custom` and `internal` directories. " .
"Should be only in one location."
);
}
}
}
+23 -9
View File
@@ -32,6 +32,8 @@ namespace Espo\Core\Utils;
use Espo\Core\{
Utils\File\Manager as FileManager,
Utils\Client\DevModeJsFileListProvider,
Utils\Module,
Utils\Json,
};
/**
@@ -39,14 +41,6 @@ use Espo\Core\{
*/
class ClientManager
{
private $themeManager;
private $config;
private $metadata;
private $fileManager;
protected $mainHtmlFilePath = 'html/main.html';
protected $runScript = "app.start();";
@@ -55,20 +49,32 @@ class ClientManager
private $libsConfigPath = 'client/cfg/libs.json';
private $themeManager;
private $config;
private $metadata;
private $fileManager;
private $devModeJsFileListProvider;
private $module;
public function __construct(
Config $config,
ThemeManager $themeManager,
Metadata $metadata,
FileManager $fileManager,
DevModeJsFileListProvider $devModeJsFileListProvider
DevModeJsFileListProvider $devModeJsFileListProvider,
Module $module
) {
$this->config = $config;
$this->themeManager = $themeManager;
$this->metadata = $metadata;
$this->fileManager = $fileManager;
$this->devModeJsFileListProvider = $devModeJsFileListProvider;
$this->module = $module;
}
public function setBasePath(string $basePath): void
@@ -166,6 +172,13 @@ class ClientManager
$faviconPath = $this->metadata->get(['app', 'client', 'favicon']) ?? 'client/img/favicon.ico';
$internalModuleList = array_map(
function (string $moduleName): string {
return Util::fromCamelCase($moduleName, '-');
},
$this->module->getInternalList()
);
$data = [
'applicationId' => 'espocrm-application-id',
'apiUrl' => 'api/v1',
@@ -184,6 +197,7 @@ class ClientManager
'faviconPath' => $faviconPath,
'ajaxTimeout' => $this->config->get('ajaxTimeout') ?? 60000,
'libsConfigPath' => $this->libsConfigPath,
'internalModuleList' => Json::encode($internalModuleList),
];
$html = $this->fileManager->getContents($htmlFilePath);
+12 -2
View File
@@ -145,7 +145,12 @@ class Module
return array_keys($modulesToSort);
}
private function getInternalList(): array
/**
* Get the list of internal modules.
*
* @return string[]
*/
public function getInternalList(): array
{
if ($this->internalList === null) {
$this->internalList = $this->fileManager->getDirList($this->internalPath);
@@ -166,7 +171,12 @@ class Module
return $basePath . '/' . $moduleName;
}
private function getList(): array
/**
* Get the list of modules. Not ordered.
*
* @return string[]
*/
public function getList(): array
{
if ($this->list === null) {
$this->list = array_merge(
+1 -2
View File
@@ -1,4 +1,3 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
!modules
+2
View File
@@ -0,0 +1,2 @@
*
!.gitignore
+31 -19
View File
@@ -102,6 +102,7 @@ define(
this.apiUrl = options.apiUrl || this.apiUrl;
this.basePath = options.basePath || '';
this.ajaxTimeout = options.ajaxTimeout || 0;
this.internalModuleList = options.internalModuleList || [];
this.initCache(options)
.then(() => this.init(options, callback));
@@ -532,7 +533,17 @@ define(
require(Utils.composeViewClassName(viewName), callback);
};
var getResourceInnerPath = function (type, name) {
let internalModuleMap = {};
let isModuleInternal = (module) => {
if (!(module in internalModuleMap)) {
internalModuleMap[module] = this.internalModuleList.indexOf(module) !== -1;
}
return internalModuleMap[module];
};
let getResourceInnerPath = (type, name) => {
let path = null;
switch (type) {
@@ -557,25 +568,26 @@ define(
}
return path;
};
}.bind(this);
var getResourcePath = (type, name) => {
if (name.indexOf(':') !== -1) {
let arr = name.split(':');
name = arr[1];
var mod = arr[0];
if (mod === 'custom') {
return 'client/custom/' + getResourceInnerPath(type, name);
}
return 'client/modules/' + mod + '/' + getResourceInnerPath(type, name);
let getResourcePath = (type, name) => {
if (name.indexOf(':') === -1) {
return 'client/' + getResourceInnerPath(type, name);
}
return 'client/' + getResourceInnerPath(type, name);
let arr = name.split(':');
let mod = arr[0];
let path = arr[1];
if (mod === 'custom') {
return 'client/custom/' + getResourceInnerPath(type, path);
}
if (isModuleInternal(mod)) {
return 'client/modules/' + mod + '/' + getResourceInnerPath(type, path);
}
return 'client/custom/modules/' + mod + '/' + getResourceInnerPath(type, path);
};
this.viewFactory = new Bull.Factory({
@@ -585,12 +597,12 @@ define(
viewLoader: this.viewLoader,
resources: {
loaders: {
'template': (name, callback) => {
template: (name, callback) => {
var path = getResourcePath('template', name);
this.loader.load('res!' + path, callback);
},
'layoutTemplate': (name, callback) => {
layoutTemplate: (name, callback) => {
var path = getResourcePath('layoutTemplate', name);
this.loader.load('res!' + path, callback);
+29 -18
View File
@@ -42,6 +42,8 @@ var Espo = Espo || {classMap: {}};
this._loadingSubject = null;
this._responseCache = null;
this._basePath = '';
this._internalModuleList = [];
this._internalModuleMap = {};
this.isDeveloperMode = false;
};
@@ -76,6 +78,11 @@ var Espo = Espo || {classMap: {}};
this._responseCache = responseCache;
},
setInternalModuleList: function (internalModuleList) {
this._internalModuleList = internalModuleList;
this._internalModuleMap = {};
},
_getClass: function (name) {
if (name in this._classMap) {
return this._classMap[name];
@@ -89,27 +96,23 @@ var Espo = Espo || {classMap: {}};
},
_nameToPath: function (name) {
let path;
if (name.indexOf(':') !== -1) {
let arr = name.split(':');
let namePart = arr[1];
let modulePart = arr[0];
if (modulePart === 'custom') {
path = 'client/custom/src/' + namePart;
}
else {
path = 'client/modules/' + modulePart + '/src/' + namePart;
}
}
else {
path = 'client/src/' + name;
if (name.indexOf(':') === -1) {
return 'client/src/' + name + '.js';
}
path += '.js';
let arr = name.split(':');
let namePart = arr[1];
let modulePart = arr[0];
return path;
if (modulePart === 'custom') {
return 'client/custom/src/' + namePart + '.js' ;
}
if (this._isModuleInternal(modulePart)) {
return'client/modules/' + modulePart + '/src/' + namePart + '.js';
}
return 'client/custom/modules/' + modulePart + '/src/' + namePart + '.js';
},
_execute: function (script) {
@@ -545,6 +548,14 @@ var Espo = Espo || {classMap: {}};
addLibsConfig: function (data) {
this._libsConfig = _.extend(this._libsConfig, data);
},
_isModuleInternal: function (moduleName) {
if (!(moduleName in this._internalModuleMap)) {
this._internalModuleMap[moduleName] = this._internalModuleList.indexOf(moduleName) !== -1;
}
return this._internalModuleMap[moduleName];
},
});
Espo.loader = new Espo.Loader();
+2
View File
@@ -19,6 +19,7 @@
window.addEventListener('DOMContentLoaded', () => {
Espo.loader.setCacheTimestamp({{loaderCacheTimestamp}});
Espo.loader.setBasePath('{{basePath}}');
Espo.loader.setInternalModuleList({{internalModuleList}});
Espo.loader
.loadLibsConfig('{{libsConfigPath}}')
@@ -31,6 +32,7 @@
basePath: '{{basePath}}',
apiUrl: '{{apiUrl}}',
ajaxTimeout: {{ajaxTimeout}},
internalModuleList: {{internalModuleList}},
}, app => {
{{runScript}}
});