mirror of
https://github.com/espocrm/espocrm.git
synced 2026-03-09 22:17:00 +00:00
Compare commits
249 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e557782c64 | ||
|
|
7cc7f3fbcf | ||
|
|
3f293a6d23 | ||
|
|
309b09f6ce | ||
|
|
0b7e9f3d62 | ||
|
|
58c17ffd5c | ||
|
|
7d3ba23a9f | ||
|
|
ca2e4f5b37 | ||
|
|
d82174fec5 | ||
|
|
033c65b79b | ||
|
|
dbc8e5d9cc | ||
|
|
42407935d5 | ||
|
|
e7d558b0bf | ||
|
|
290b530b92 | ||
|
|
18726bdccd | ||
|
|
06b0498abb | ||
|
|
7a7627e931 | ||
|
|
c6038e9cee | ||
|
|
0e05596155 | ||
|
|
0ca212f911 | ||
|
|
94c2b9deda | ||
|
|
2016a1bb0d | ||
|
|
6841ba9c85 | ||
|
|
d5988f2c04 | ||
|
|
a56c9c3a46 | ||
|
|
9d0bbdcd4d | ||
|
|
4bfaac3414 | ||
|
|
d54c044fd9 | ||
|
|
1def66bb77 | ||
|
|
75041db2e9 | ||
|
|
356948cdf7 | ||
|
|
db92abf3ee | ||
|
|
d5d59abf13 | ||
|
|
69c1e3e8e0 | ||
|
|
963c4e3e2b | ||
|
|
cc4c735a27 | ||
|
|
175517a9dc | ||
|
|
9cb3548393 | ||
|
|
ac0dea317f | ||
|
|
839dfb9709 | ||
|
|
2c7a4098f3 | ||
|
|
0228396376 | ||
|
|
c5aa0eba48 | ||
|
|
ac4472975d | ||
|
|
379f5fbaaf | ||
|
|
af71408c52 | ||
|
|
b7a4fa1e7c | ||
|
|
92b6e45ef2 | ||
|
|
acf6f67627 | ||
|
|
017c34dcde | ||
|
|
f6e54918b2 | ||
|
|
75b3c33526 | ||
|
|
f784760735 | ||
|
|
a739b3a96e | ||
|
|
0a8e0f00c2 | ||
|
|
00c4cf4893 | ||
|
|
e8e9ea9e2f | ||
|
|
c9cdb6767b | ||
|
|
24f9c1c762 | ||
|
|
766a880799 | ||
|
|
07de0dbeb0 | ||
|
|
d1752f2ff0 | ||
|
|
ef27234ef8 | ||
|
|
685862f1de | ||
|
|
97621c45a8 | ||
|
|
b96d433796 | ||
|
|
03d784c284 | ||
|
|
02ef97724f | ||
|
|
93e2c65d30 | ||
|
|
d02bf65a55 | ||
|
|
fb2f566314 | ||
|
|
2227870854 | ||
|
|
b195509843 | ||
|
|
2100fa0606 | ||
|
|
3fe43bdfa3 | ||
|
|
26ad3d48af | ||
|
|
9c224fefb7 | ||
|
|
e4db873e43 | ||
|
|
f06d53b3d2 | ||
|
|
4ef706b716 | ||
|
|
09e364625d | ||
|
|
35f575ed7f | ||
|
|
7b0d46b37f | ||
|
|
b8be2c9e13 | ||
|
|
f05c763119 | ||
|
|
262b3bb3b3 | ||
|
|
f474137b91 | ||
|
|
7a18d88c50 | ||
|
|
d3ea71c726 | ||
|
|
8d1c9fe666 | ||
|
|
62ccfaa9c0 | ||
|
|
e6566bccdc | ||
|
|
14ed7282f3 | ||
|
|
b13145adce | ||
|
|
c0b169f7dd | ||
|
|
3cfca9845a | ||
|
|
afa8d07bb4 | ||
|
|
02434e0ca1 | ||
|
|
3d68c77ed4 | ||
|
|
11f76c507b | ||
|
|
a2e241966e | ||
|
|
c68f3eb44d | ||
|
|
6a1d8dcdca | ||
|
|
ba358e5847 | ||
|
|
5e174fd5a9 | ||
|
|
7bf7944360 | ||
|
|
9f72b074d5 | ||
|
|
9af2500292 | ||
|
|
59b7934aa2 | ||
|
|
8e9dea260e | ||
|
|
29ed6cb3b0 | ||
|
|
a7a61a993c | ||
|
|
68d1c0854b | ||
|
|
fdd6f01415 | ||
|
|
4670bb49e8 | ||
|
|
54a045e25a | ||
|
|
fcc18befc3 | ||
|
|
52ac9b1621 | ||
|
|
862b76f165 | ||
|
|
9bca545f01 | ||
|
|
80032f8ed7 | ||
|
|
a63a690307 | ||
|
|
5ed0b2ba6b | ||
|
|
24dc2716f7 | ||
|
|
bbe26618ac | ||
|
|
6f65d9e8d8 | ||
|
|
3f40896374 | ||
|
|
f1b0decbab | ||
|
|
8d8778b397 | ||
|
|
c2b60698bc | ||
|
|
68d3b422cc | ||
|
|
63ff4c1dca | ||
|
|
145420aaaa | ||
|
|
8987ec61fe | ||
|
|
34ee17b7f5 | ||
|
|
a93627d274 | ||
|
|
90fe18b660 | ||
|
|
2a0646d1dd | ||
|
|
6182376d1f | ||
|
|
52620e84cd | ||
|
|
66235f7e77 | ||
|
|
49b61dab53 | ||
|
|
4747113742 | ||
|
|
a10f2949a4 | ||
|
|
f26d7c6a62 | ||
|
|
2e0d8cfd43 | ||
|
|
666d8ab5ad | ||
|
|
db57c53652 | ||
|
|
bbcf9e00fa | ||
|
|
badf1aec6f | ||
|
|
19bb4514df | ||
|
|
778be7fea8 | ||
|
|
326970bcd4 | ||
|
|
9411bce8b0 | ||
|
|
244c1a426b | ||
|
|
b3f9ca8721 | ||
|
|
8c66a83054 | ||
|
|
df6a1f6613 | ||
|
|
1033a926fc | ||
|
|
d339c04177 | ||
|
|
edcf0aae84 | ||
|
|
20f97caab3 | ||
|
|
86be4e7352 | ||
|
|
697e271e66 | ||
|
|
5f74504da8 | ||
|
|
fb3d46d389 | ||
|
|
875971fb6e | ||
|
|
1939a58f17 | ||
|
|
40b3374fdd | ||
|
|
c564b1b75a | ||
|
|
c28e73ce3f | ||
|
|
788a6bfdc3 | ||
|
|
15d1f79115 | ||
|
|
bf699d88f7 | ||
|
|
d7f8e4e050 | ||
|
|
3872d7897a | ||
|
|
17a1f6ce63 | ||
|
|
eaa155eff7 | ||
|
|
13fba6d71c | ||
|
|
0d423aa349 | ||
|
|
2fca224ba4 | ||
|
|
574f85df46 | ||
|
|
b7176983e2 | ||
|
|
e8f19ff0dc | ||
|
|
d3cb4607ea | ||
|
|
8ae0696f07 | ||
|
|
299c3c13fc | ||
|
|
a79a8bcef6 | ||
|
|
2a0dd46b5e | ||
|
|
6c287bc2e2 | ||
|
|
7add59ffcb | ||
|
|
9747c43988 | ||
|
|
8b9a0f1437 | ||
|
|
1315ca007c | ||
|
|
e753d767fc | ||
|
|
db893859c2 | ||
|
|
16af3d2ad8 | ||
|
|
f334080fe6 | ||
|
|
b2acfbed98 | ||
|
|
2aca6ca28a | ||
|
|
c96040edec | ||
|
|
e0ebb44e64 | ||
|
|
ee1af88f8d | ||
|
|
1659e583ea | ||
|
|
6f0575d798 | ||
|
|
ba05c45f47 | ||
|
|
353caf29b3 | ||
|
|
7600d473bb | ||
|
|
c9ff48245e | ||
|
|
4ed4a94209 | ||
|
|
c88e01fe75 | ||
|
|
9e46edce79 | ||
|
|
bae5c67839 | ||
|
|
635d5d9c6c | ||
|
|
65be8c385f | ||
|
|
c3d44e2472 | ||
|
|
4a781ed5f4 | ||
|
|
d9995512a1 | ||
|
|
6ed2466785 | ||
|
|
724c74b488 | ||
|
|
67887c5ba4 | ||
|
|
ea2a0068ed | ||
|
|
0bfdea5976 | ||
|
|
305ebc293f | ||
|
|
f17f74672e | ||
|
|
fcaf184b13 | ||
|
|
efe653f1f6 | ||
|
|
c1022bf8f3 | ||
|
|
0f4c3988f8 | ||
|
|
498b7b5679 | ||
|
|
ca445a3cb7 | ||
|
|
8a293749e0 | ||
|
|
5c034279e8 | ||
|
|
9460943ad2 | ||
|
|
5eaeabe231 | ||
|
|
2202b00600 | ||
|
|
68ba5a5c4a | ||
|
|
e80b490152 | ||
|
|
380937b644 | ||
|
|
ac72305101 | ||
|
|
a41779b0bb | ||
|
|
86cdbf24b7 | ||
|
|
5d7bc98088 | ||
|
|
1359e8eb2f | ||
|
|
f3a7003444 | ||
|
|
624f76b1a0 | ||
|
|
484ffa071c | ||
|
|
850fb3cb15 | ||
|
|
40075ed2e3 |
@@ -63,7 +63,7 @@ class Admin extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
$scheduledJob = $this->getContainer()->get('scheduledJob');
|
||||
|
||||
return $scheduledJob->getAllNamesOnly();
|
||||
return $scheduledJob->getAvailableList();
|
||||
}
|
||||
|
||||
public function postActionUploadUpgradePackage($params, $data)
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
@@ -34,17 +34,19 @@ use \Espo\Core\Exceptions\Error;
|
||||
class EmailTemplate extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
public function actionParse($params, $data, $request)
|
||||
{
|
||||
{
|
||||
$id = $request->get('id');
|
||||
$emailAddress = $request->get('emailAddress');
|
||||
if (empty($id)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
|
||||
return $this->getRecordService()->parse($id, array(
|
||||
'emailAddress' => $request->get('emailAddress'),
|
||||
'parentType' => $request->get('parentType'),
|
||||
'parentId' => $request->get('parentId'),
|
||||
'relatedType' => $request->get('relatedType'),
|
||||
'relatedId' => $request->get('relatedId')
|
||||
), true);
|
||||
}
|
||||
|
||||
|
||||
78
application/Espo/Controllers/LabelManager.php
Normal file
78
application/Espo/Controllers/LabelManager.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Utils as Utils;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class LabelManager extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
public function postActionGetScopeList($params)
|
||||
{
|
||||
$labelManager = $this->getContainer()->get('injectableFactory')->createByClassName('\\Espo\\Core\\Utils\\LabelManager');
|
||||
|
||||
return $labelManager->getScopeList();
|
||||
}
|
||||
|
||||
public function postActionGetScopeData($params, $data, $request)
|
||||
{
|
||||
if (empty($data['scope']) || empty($data['language'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$labelManager = $this->getContainer()->get('injectableFactory')->createByClassName('\\Espo\\Core\\Utils\\LabelManager');
|
||||
return $labelManager->getScopeData($data['language'], $data['scope']);
|
||||
}
|
||||
|
||||
public function postActionSaveLabels($params, $data)
|
||||
{
|
||||
if (empty($data['scope']) || empty($data['language']) || !isset($data['labels'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$labels = get_object_vars($data['labels']);
|
||||
|
||||
$labelManager = $this->getContainer()->get('injectableFactory')->createByClassName('\\Espo\\Core\\Utils\\LabelManager');
|
||||
$returnData = $labelManager->saveLabels($data['language'], $data['scope'], $labels);
|
||||
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
|
||||
return $returnData;
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,11 @@ class Settings extends \Espo\Core\Controllers\Base
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
if (isset($data['useCache']) && $data['useCache'] != $this->getConfig()->get('useCache')) {
|
||||
if (
|
||||
(isset($data['useCache']) && $data['useCache'] != $this->getConfig()->get('useCache'))
|
||||
||
|
||||
(isset($data['aclStrictMode']) && $data['aclStrictMode'] !== $this->getConfig()->get('aclStrictMode'))
|
||||
) {
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ use \Espo\Entities\User;
|
||||
|
||||
use \Espo\Core\Utils\Config;
|
||||
use \Espo\Core\Utils\Metadata;
|
||||
use \Espo\Core\Utils\FieldManager;
|
||||
use \Espo\Core\Utils\FieldManagerUtil;
|
||||
use \Espo\Core\Utils\File\Manager as FileManager;
|
||||
|
||||
class Table
|
||||
@@ -77,7 +77,9 @@ class Table
|
||||
|
||||
protected $forbiddenFieldsCache = array();
|
||||
|
||||
public function __construct(User $user, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManager $fieldManager = null)
|
||||
protected $isStrictMode = false;
|
||||
|
||||
public function __construct(User $user, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManagerUtil $fieldManager = null)
|
||||
{
|
||||
$this->data = (object) [
|
||||
'table' => (object) [],
|
||||
@@ -85,6 +87,8 @@ class Table
|
||||
'fieldTableQuickAccess' => (object) [],
|
||||
];
|
||||
|
||||
$this->isStrictMode = $config->get('aclStrictMode', false);
|
||||
|
||||
$this->user = $user;
|
||||
|
||||
$this->metadata = $metadata;
|
||||
@@ -135,11 +139,6 @@ class Table
|
||||
return $this->fieldManager;
|
||||
}
|
||||
|
||||
protected function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function getMap()
|
||||
{
|
||||
return $this->data;
|
||||
@@ -454,7 +453,11 @@ class Table
|
||||
$aclType = $this->defaultAclType;
|
||||
}
|
||||
if (!empty($aclType)) {
|
||||
$defaultValue = $this->metadata->get('app.'.$this->type.'.scopeLevelTypesDefaults.' . $aclType, $this->metadata->get('app.'.$this->type.'.scopeLevelTypesDefaults.record'));
|
||||
$paramDefaultsName = 'scopeLevelTypesDefaults';
|
||||
if ($this->isStrictMode) {
|
||||
$paramDefaultsName = 'scopeLevelTypesStrictDefaults';
|
||||
}
|
||||
$defaultValue = $this->metadata->get(['app', $this->type, $paramDefaultsName, $aclType], $this->metadata->get(['app', $this->type, $paramDefaultsName, 'record']));
|
||||
if (is_array($defaultValue)) {
|
||||
$defaultValue = (object) $defaultValue;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ class AclManager
|
||||
$config = $this->getContainer()->get('config');
|
||||
$fileManager = $this->getContainer()->get('fileManager');
|
||||
$metadata = $this->getContainer()->get('metadata');
|
||||
$fieldManager = $this->getContainer()->get('fieldManager');
|
||||
$fieldManager = $this->getContainer()->get('fieldManagerUtil');
|
||||
|
||||
$this->tableHashMap[$key] = new $this->tableClassName($user, $config, $fileManager, $metadata, $fieldManager);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ use \Espo\Entities\Portal;
|
||||
|
||||
use \Espo\Core\Utils\Config;
|
||||
use \Espo\Core\Utils\Metadata;
|
||||
use \Espo\Core\Utils\FieldManager;
|
||||
use \Espo\Core\Utils\FieldManagerUtil;
|
||||
use \Espo\Core\Utils\File\Manager as FileManager;
|
||||
|
||||
class Table extends \Espo\Core\Acl\Table
|
||||
@@ -52,7 +52,7 @@ class Table extends \Espo\Core\Acl\Table
|
||||
|
||||
protected $valuePermissionList = [];
|
||||
|
||||
public function __construct(User $user, Portal $portal, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManager $fieldManager = null)
|
||||
public function __construct(User $user, Portal $portal, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManagerUtil $fieldManager = null)
|
||||
{
|
||||
if (empty($portal)) {
|
||||
throw new Error("No portal was passed to AclPortal\\Table constructor.");
|
||||
|
||||
@@ -93,31 +93,6 @@ class Container
|
||||
return $className;
|
||||
}
|
||||
|
||||
protected function loadLog()
|
||||
{
|
||||
$config = $this->get('config');
|
||||
|
||||
$path = $config->get('logger.path', 'data/logs/espo.log');
|
||||
$rotation = $config->get('logger.rotation', true);
|
||||
|
||||
$log = new \Espo\Core\Utils\Log('Espo');
|
||||
$levelCode = $log->getLevelCode($config->get('logger.level', 'WARNING'));
|
||||
|
||||
if ($rotation) {
|
||||
$maxFileNumber = $config->get('logger.maxFileNumber', 30);
|
||||
$handler = new \Espo\Core\Utils\Log\Monolog\Handler\RotatingFileHandler($path, $maxFileNumber, $levelCode);
|
||||
} else {
|
||||
$handler = new \Espo\Core\Utils\Log\Monolog\Handler\StreamHandler($path, $levelCode);
|
||||
}
|
||||
$log->pushHandler($handler);
|
||||
|
||||
$errorHandler = new \Monolog\ErrorHandler($log);
|
||||
$errorHandler->registerExceptionHandler(null, false);
|
||||
$errorHandler->registerErrorHandler(array(), false);
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
protected function loadContainer()
|
||||
{
|
||||
return $this;
|
||||
@@ -335,6 +310,13 @@ class Container
|
||||
);
|
||||
}
|
||||
|
||||
protected function loadFieldManagerUtil()
|
||||
{
|
||||
return new \Espo\Core\Utils\FieldManagerUtil(
|
||||
$this->get('metadata')
|
||||
);
|
||||
}
|
||||
|
||||
protected function loadThemeManager()
|
||||
{
|
||||
return new \Espo\Core\Utils\ThemeManager(
|
||||
|
||||
@@ -60,9 +60,9 @@ class ControllerManager
|
||||
|
||||
public function process($controllerName, $actionName, $params, $data, $request)
|
||||
{
|
||||
$customeClassName = '\\Espo\\Custom\\Controllers\\' . Util::normilizeClassName($controllerName);
|
||||
if (class_exists($customeClassName)) {
|
||||
$controllerClassName = $customeClassName;
|
||||
$customClassName = '\\Espo\\Custom\\Controllers\\' . Util::normilizeClassName($controllerName);
|
||||
if (class_exists($customClassName)) {
|
||||
$controllerClassName = $customClassName;
|
||||
} else {
|
||||
$moduleName = $this->metadata->getScopeModuleName($controllerName);
|
||||
if ($moduleName) {
|
||||
|
||||
@@ -258,6 +258,14 @@ class Record extends Base
|
||||
$params['attributeList'] = $data['attributeList'];
|
||||
}
|
||||
|
||||
if (isset($data['fieldList'])) {
|
||||
$params['fieldList'] = $data['fieldList'];
|
||||
}
|
||||
|
||||
if (isset($data['format'])) {
|
||||
$params['format'] = $data['format'];
|
||||
}
|
||||
|
||||
return array(
|
||||
'id' => $this->getRecordService()->export($params)
|
||||
);
|
||||
|
||||
@@ -283,24 +283,20 @@ class CronManager
|
||||
}
|
||||
|
||||
try {
|
||||
$previousDate = $cronExpression->getPreviousRunDate()->format('Y-m-d H:i:s');
|
||||
$nextDate = $cronExpression->getNextRunDate()->format('Y-m-d H:i:s');
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('CronManager (ScheduledJob ['.$scheduledJob['id'].']): Unsupported CRON expression ['.$scheduling.']');
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($cronExpression->isDue()) {
|
||||
$previousDate = date('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
$existingJob = $this->getCronJob()->getJobByScheduledJob($scheduledJob['id'], $previousDate);
|
||||
$existingJob = $this->getCronJob()->getJobByScheduledJob($scheduledJob['id'], $nextDate);
|
||||
if ($existingJob) continue;
|
||||
|
||||
$className = $this->getScheduledJobUtil()->get($scheduledJob['job']);
|
||||
if ($className) {
|
||||
if (method_exists($className, 'prepare')) {
|
||||
$implementation = new $className($this->container);
|
||||
$implementation->prepare($scheduledJob, $previousDate);
|
||||
$implementation->prepare($scheduledJob, $nextDate);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -314,7 +310,7 @@ class CronManager
|
||||
'name' => $scheduledJob['name'],
|
||||
'status' => self::PENDING,
|
||||
'scheduledJobId' => $scheduledJob['id'],
|
||||
'executeTime' => $previousDate,
|
||||
'executeTime' => $nextDate,
|
||||
'method' => $scheduledJob['job']
|
||||
));
|
||||
$this->getEntityManager()->saveEntity($jobEntity);
|
||||
|
||||
@@ -59,6 +59,8 @@ class DataManager
|
||||
|
||||
$result &= $this->rebuildDatabase($entityList);
|
||||
|
||||
$this->rebuildScheduledJobs();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -121,6 +123,40 @@ class DataManager
|
||||
return empty($ormData) ? false : true;
|
||||
}
|
||||
|
||||
public function rebuildScheduledJobs()
|
||||
{
|
||||
$metadata = $this->getContainer()->get('metadata');
|
||||
$entityManager = $this->getContainer()->get('entityManager');
|
||||
|
||||
$jobs = $metadata->get(['entityDefs', 'ScheduledJob', 'jobs'], array());
|
||||
|
||||
foreach ($jobs as $jobName => $defs) {
|
||||
if ($jobName && !empty($defs['isSystem']) && !empty($defs['scheduling'])) {
|
||||
if (!$entityManager->getRepository('ScheduledJob')->where(array(
|
||||
'job' => $jobName,
|
||||
'status' => 'Active',
|
||||
'scheduling' => $defs['scheduling']
|
||||
))->findOne()) {
|
||||
$job = $entityManager->getRepository('ScheduledJob')->where(array(
|
||||
'job' => $jobName
|
||||
))->findOne();
|
||||
if ($job) {
|
||||
$entityManager->removeEntity($job);
|
||||
}
|
||||
$job = $entityManager->getEntity('ScheduledJob');
|
||||
$job->set(array(
|
||||
'job' => $jobName,
|
||||
'status' => 'Active',
|
||||
'scheduling' => $defs['scheduling'],
|
||||
'isInternal' => true,
|
||||
'name' => $jobName
|
||||
));
|
||||
$entityManager->saveEntity($job);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update cache timestamp
|
||||
*
|
||||
|
||||
65
application/Espo/Core/Export/Csv.php
Normal file
65
application/Espo/Core/Export/Csv.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Export;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class Csv extends \Espo\Core\Injectable
|
||||
{
|
||||
protected $dependencyList = [
|
||||
'config',
|
||||
'preferences'
|
||||
];
|
||||
|
||||
public function process($entityType, $params, $dataList)
|
||||
{
|
||||
if (!is_array($params['attributeList'])) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$attributeList = $params['attributeList'];
|
||||
|
||||
$delimiter = $this->getInjection('preferences')->get('exportDelimiter');
|
||||
if (empty($delimiter)) {
|
||||
$delimiter = $this->getInjection('config')->get('exportDelimiter', ';');
|
||||
}
|
||||
|
||||
$fp = fopen('php://temp', 'w');
|
||||
fputcsv($fp, $attributeList, $delimiter);
|
||||
foreach ($dataList as $row) {
|
||||
fputcsv($fp, $row, $delimiter);
|
||||
}
|
||||
rewind($fp);
|
||||
$csv = stream_get_contents($fp);
|
||||
fclose($fp);
|
||||
|
||||
return $csv;
|
||||
}
|
||||
}
|
||||
459
application/Espo/Core/Export/Xlsx.php
Normal file
459
application/Espo/Core/Export/Xlsx.php
Normal file
@@ -0,0 +1,459 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Export;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class Xlsx extends \Espo\Core\Injectable
|
||||
{
|
||||
protected $dependencyList = [
|
||||
'language',
|
||||
'metadata',
|
||||
'config',
|
||||
'dateTime',
|
||||
'entityManager',
|
||||
'fileStorageManager',
|
||||
'fileManager'
|
||||
];
|
||||
|
||||
protected function getConfig()
|
||||
{
|
||||
return $this->getInjection('config');
|
||||
}
|
||||
|
||||
protected function getMetadata()
|
||||
{
|
||||
return $this->getInjection('metadata');
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
{
|
||||
return $this->getInjection('entityManager');
|
||||
}
|
||||
|
||||
public function loadAdditionalFields(Entity $entity, $fieldList)
|
||||
{
|
||||
foreach ($entity->getRelationList() as $link) {
|
||||
if ($entity->getRelationType($link) === 'belongsToParent') {
|
||||
if (in_array($link, $fieldList)) {
|
||||
$parent = $entity->get($link);
|
||||
if ($parent instanceof Entity) {
|
||||
$entity->set($link . 'Name', $parent->get('name'));
|
||||
}
|
||||
}
|
||||
} else if ($entity->getRelationType($link) === 'belongsTo' && $entity->getRelationParam($link, 'noJoin') && $entity->hasField($link . 'Name')) {
|
||||
if (in_array($link, $fieldList)) {
|
||||
$related = $entity->get($link);
|
||||
if ($related instanceof Entity) {
|
||||
$entity->set($link . 'Name', $related->get('name'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addAdditionalAttributes($entityType, &$attributeList, $fieldList)
|
||||
{
|
||||
$linkList = [];
|
||||
|
||||
if (!in_array('id', $attributeList)) {
|
||||
$attributeList[] = 'id';
|
||||
}
|
||||
|
||||
$linkDefs = $this->getMetadata()->get(['entityDefs', $entityType, 'links']);
|
||||
if (is_array($linkDefs)) {
|
||||
foreach ($linkDefs as $link => $defs) {
|
||||
if (empty($defs['type'])) continue;
|
||||
if ($defs['type'] === 'belongsToParent') {
|
||||
$linkList[] = $link;
|
||||
} else if ($defs['type'] === 'belongsTo' && !empty($defs['noJoin'])) {
|
||||
if ($this->getMetadata()->get(['entityDefs', $entityType, 'fields', $link])) {
|
||||
$linkList[] = $link;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($linkList as $item) {
|
||||
if (in_array($item, $fieldList) && !in_array($item . 'Name', $attributeList)) {
|
||||
$attributeList[] = $item . 'Name';
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($fieldList as $field) {
|
||||
$type = $this->getMetadata()->get(['entityDefs', $entityType, 'fields', $field, 'type']);
|
||||
if ($type === 'currencyConverted') {
|
||||
if (!in_array($field, $attributeList)) {
|
||||
$attributeList[] = $field;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function process($entityType, $params, $dataList)
|
||||
{
|
||||
if (!is_array($params['fieldList'])) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$phpExcel = new \PHPExcel();
|
||||
$sheet = $phpExcel->setActiveSheetIndex(0);
|
||||
|
||||
if (isset($params['exportName'])) {
|
||||
$exportName = $params['exportName'];
|
||||
} else {
|
||||
$exportName = $this->getInjection('language')->translate($entityType, 'scopeNamesPlural');
|
||||
}
|
||||
|
||||
$sheetName = substr($exportName, 0, 30);
|
||||
$badCharList = ['*', ':', '/', '\\', '?', '[', ']'];
|
||||
foreach ($badCharList as $badChar) {
|
||||
$sheetName = str_replace($badCharList, ' ', $sheetName);
|
||||
}
|
||||
$sheetName = str_replace('\'', '', $sheetName);
|
||||
|
||||
$sheet->setTitle($sheetName);
|
||||
|
||||
$fieldList = $params['fieldList'];
|
||||
|
||||
$titleStyle = array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 12
|
||||
)
|
||||
);
|
||||
$dateStyle = array(
|
||||
'font' => array(
|
||||
'size' => 12
|
||||
)
|
||||
);
|
||||
|
||||
$sheet->setCellValue('A1', $exportName);
|
||||
|
||||
$sheet->setCellValue('B1', \PHPExcel_Shared_Date::PHPToExcel(strtotime(date('Y-m-d H:i:s'))));
|
||||
|
||||
|
||||
$sheet->getStyle('A1')->applyFromArray($titleStyle);
|
||||
$sheet->getStyle('B1')->applyFromArray($dateStyle);
|
||||
|
||||
$sheet->getStyle('B1')->getNumberFormat()
|
||||
->setFormatCode($this->getInjection('dateTime')->getDateTimeFormat());
|
||||
|
||||
$azRange = range('A', 'Z');
|
||||
$azRangeCopied = $azRange;
|
||||
foreach ($azRangeCopied as $i => $char1) {
|
||||
foreach ($azRangeCopied as $j => $char2) {
|
||||
$azRange[] = $char1 . $char2;
|
||||
if ($i * count($azRangeCopied) + $j === count($fieldList)) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rowNumber = 3;
|
||||
|
||||
$linkColList = [];
|
||||
|
||||
$lastIndex = 0;
|
||||
|
||||
foreach ($fieldList as $i => $name) {
|
||||
$col = $azRange[$i];
|
||||
|
||||
$defs = $this->getInjection('metadata')->get(['entityDefs', $entityType, 'fields', $name]);
|
||||
|
||||
if (!$defs) {
|
||||
$defs['type'] = 'base';
|
||||
}
|
||||
|
||||
$label = $name;
|
||||
if (strpos($name, '_') !== false) {
|
||||
list($linkName, $foreignField) = explode('_', $name);
|
||||
$foreignScope = $this->getInjection('metadata')->get(['entityDefs', $entityType, 'links', $linkName, 'entity']);
|
||||
if ($foreignScope) {
|
||||
$label = $this->getInjection('language')->translate($linkName, 'links', $entityType) . '.' . $this->getInjection('language')->translate($foreignField, 'fields', $foreignScope);
|
||||
}
|
||||
} else {
|
||||
$label = $this->getInjection('language')->translate($name, 'fields', $entityType);
|
||||
}
|
||||
|
||||
$sheet->setCellValue($col . $rowNumber, $label);
|
||||
$sheet->getColumnDimension($col)->setAutoSize(true);
|
||||
if (in_array($defs['type'], ['phone', 'email', 'url', 'link', 'linkParent'])) {
|
||||
$linkColList[] = $col;
|
||||
} else if ($name == 'name') {
|
||||
$linkColList[] = $col;
|
||||
}
|
||||
$lastIndex = $i;
|
||||
}
|
||||
|
||||
$col = $azRange[$i];
|
||||
|
||||
$headerStyle = array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 12
|
||||
)
|
||||
);
|
||||
|
||||
$sheet->getStyle("A$rowNumber:$col$rowNumber")->applyFromArray($headerStyle);
|
||||
$sheet->setAutoFilter("A$rowNumber:$col$rowNumber");
|
||||
|
||||
$typesCache = array();
|
||||
|
||||
$rowNumber++;
|
||||
foreach ($dataList as $row) {
|
||||
$i = 0;
|
||||
foreach ($fieldList as $i => $name) {
|
||||
$col = $azRange[$i];
|
||||
|
||||
$defs = $this->getInjection('metadata')->get(['entityDefs', $entityType, 'fields', $name]);
|
||||
if (!$defs) {
|
||||
$defs = array();
|
||||
$defs['type'] = 'base';
|
||||
}
|
||||
|
||||
$type = $defs['type'];
|
||||
$foreignField = $name;
|
||||
$linkName = null;
|
||||
if (strpos($name, '_') !== false) {
|
||||
list($linkName, $foreignField) = explode('_', $name);
|
||||
$foreignScope = $this->getInjection('metadata')->get(['entityDefs', $entityType, 'links', $linkName, 'entity']);
|
||||
if ($foreignScope) {
|
||||
$type = $this->getInjection('metadata')->get(['entityDefs', $foreignScope, 'fields', $foreignField, 'type'], $type);
|
||||
}
|
||||
}
|
||||
$typesCache[$name] = $type;
|
||||
|
||||
$link = null;
|
||||
if ($type == 'link') {
|
||||
if (array_key_exists($name.'Name', $row)) {
|
||||
$sheet->setCellValue("$col$rowNumber", $row[$name.'Name']);
|
||||
}
|
||||
} else if ($type == 'linkParent') {
|
||||
if (array_key_exists($name.'Name', $row)) {
|
||||
$sheet->setCellValue("$col$rowNumber", $row[$name.'Name']);
|
||||
}
|
||||
} else if ($type == 'int') {
|
||||
$sheet->setCellValue("$col$rowNumber", $row[$name] ?: 0);
|
||||
} else if ($type == 'currency') {
|
||||
if (array_key_exists($name.'Currency', $row) && array_key_exists($name, $row)) {
|
||||
$sheet->setCellValue("$col$rowNumber", $row[$name] ? $row[$name] : '');
|
||||
$currency = $row[$name . 'Currency'];
|
||||
$currencySymbol = $this->getMetadata()->get(['app', 'currency', 'symbolMap', $currency], '');
|
||||
|
||||
$sheet->getStyle("$col$rowNumber")
|
||||
->getNumberFormat()
|
||||
->setFormatCode('[$'.$currencySymbol.'-409]#,##0.00;-[$'.$currencySymbol.'-409]#,##0.00');
|
||||
}
|
||||
} else if ($type == 'currencyConverted') {
|
||||
if (array_key_exists($name, $row)) {
|
||||
$currency = $this->getConfig()->get('baseCurrency');
|
||||
$currencySymbol = $this->getMetadata()->get(['app', 'currency', 'symbolMap', $currency], '');
|
||||
|
||||
$sheet->getStyle("$col$rowNumber")
|
||||
->getNumberFormat()
|
||||
->setFormatCode('[$'.$currencySymbol.'-409]#,##0.00;-[$'.$currencySymbol.'-409]#,##0.00');
|
||||
|
||||
$sheet->setCellValue("$col$rowNumber", $row[$name] ? $row[$name] : '');
|
||||
}
|
||||
} else if ($type == 'personName') {
|
||||
if (!empty($row['name'])) {
|
||||
$sheet->setCellValue("$col$rowNumber", $row['name']);
|
||||
} else {
|
||||
$personName = '';
|
||||
if (!empty($row['firstName'])) {
|
||||
$personName .= $row['firstName'];
|
||||
}
|
||||
if (!empty($row['lastName'])) {
|
||||
if (!empty($row['firstName'])) {
|
||||
$personName .= ' ';
|
||||
}
|
||||
$personName .= $row['lastName'];
|
||||
}
|
||||
$sheet->setCellValue("$col$rowNumber", $personName);
|
||||
}
|
||||
} else if ($type == 'date') {
|
||||
if (isset($row[$name])) {
|
||||
$sheet->setCellValue("$col$rowNumber", \PHPExcel_Shared_Date::PHPToExcel(strtotime($row[$name])));
|
||||
}
|
||||
} else if ($type == 'datetime' || $type == 'datetimeOptional') {
|
||||
if (isset($row[$name])) {
|
||||
$sheet->setCellValue("$col$rowNumber", \PHPExcel_Shared_Date::PHPToExcel(strtotime($row[$name])));
|
||||
}
|
||||
} else if ($type == 'image') {
|
||||
if (isset($row[$name . 'Id']) && $row[$name . 'Id']) {
|
||||
$attachment = $this->getEntityManager()->getEntity('Attachment', $row[$name . 'Id']);
|
||||
|
||||
if ($attachment) {
|
||||
$objDrawing = new \PHPExcel_Worksheet_Drawing();
|
||||
$filePath = $this->getInjection('fileStorageManager')->getLocalFilePath($attachment);
|
||||
|
||||
if ($filePath && file_exists($filePath)) {
|
||||
$objDrawing->setPath($filePath);
|
||||
$objDrawing->setHeight(100);
|
||||
$objDrawing->setCoordinates("$col$rowNumber");
|
||||
$objDrawing->setWorksheet($sheet);
|
||||
$sheet->getRowDimension($rowNumber)->setRowHeight(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if ($type == 'file') {
|
||||
if (array_key_exists($name.'Name', $row)) {
|
||||
$sheet->setCellValue("$col$rowNumber", $row[$name.'Name']);
|
||||
}
|
||||
} else if ($type == 'enum') {
|
||||
if (array_key_exists($name, $row)) {
|
||||
if ($linkName) {
|
||||
$value = $this->getInjection('language')->translateOption($row[$name], $foreignField, $foreignScope);
|
||||
} else {
|
||||
$value = $this->getInjection('language')->translateOption($row[$name], $name, $entityType);
|
||||
}
|
||||
$sheet->setCellValue("$col$rowNumber", $value);
|
||||
}
|
||||
} else {
|
||||
if (array_key_exists($name, $row)) {
|
||||
$sheet->setCellValue("$col$rowNumber", $row[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
$link = false;
|
||||
|
||||
if ($name == 'name') {
|
||||
if (array_key_exists('id', $row)) {
|
||||
$link = $this->getConfig()->getSiteUrl() . "/#".$entityType . "/view/" . $row['id'];
|
||||
}
|
||||
} else if ($type == 'url') {
|
||||
if (array_key_exists($name, $row) && filter_var($row[$name], FILTER_VALIDATE_URL)) {
|
||||
$link = $row[$name];
|
||||
}
|
||||
} else if ($type == 'link') {
|
||||
if (array_key_exists($name.'Id', $row)) {
|
||||
$foreignEntity = $this->getMetadata()->get(['entityDefs', $entityType, 'links', $name, 'entity']);
|
||||
if ($foreignEntity) {
|
||||
$link = $this->getConfig()->getSiteUrl() . "/#" . $foreignEntity. "/view/". $row[$name.'Id'];
|
||||
}
|
||||
}
|
||||
} else if ($type == 'file') {
|
||||
if (array_key_exists($name.'Id', $row)) {
|
||||
$link = $this->getConfig()->getSiteUrl() . "/?entryPoint=download&id=" . $row[$name.'Id'];
|
||||
}
|
||||
} else if ($type == 'linkParent') {
|
||||
if (array_key_exists($name.'Id', $row) && array_key_exists($name.'Type', $row)) {
|
||||
$link = $this->getConfig()->getSiteUrl() . "/#".$row[$name.'Type']."/view/". $row[$name.'Id'];
|
||||
}
|
||||
} else if ($type == 'phone') {
|
||||
if (array_key_exists($name, $row)) {
|
||||
$link = "tel:".$row[$name];
|
||||
}
|
||||
} else if ($type == 'email' && array_key_exists($name, $row)) {
|
||||
if (array_key_exists($name, $row)) {
|
||||
$link = "mailto:".$row[$name];
|
||||
}
|
||||
}
|
||||
if ($link) {
|
||||
$sheet->getCell("$col$rowNumber")->getHyperlink()->setUrl($link);
|
||||
$sheet->getCell("$col$rowNumber")->getHyperlink()->setTooltip($link);
|
||||
}
|
||||
}
|
||||
$rowNumber++;
|
||||
}
|
||||
|
||||
$startingRowNumber = 4;
|
||||
|
||||
foreach ($fieldList as $i => $name) {
|
||||
$col = $azRange[$i];
|
||||
|
||||
$type = $typesCache[$name];
|
||||
|
||||
if ($col == 'A') {
|
||||
$sheet->getStyle("A2:A$rowNumber")
|
||||
->getNumberFormat()
|
||||
->setFormatCode(\PHPExcel_Style_NumberFormat::FORMAT_TEXT);
|
||||
} else {
|
||||
switch($type) {
|
||||
case 'currency':
|
||||
case 'currencyConverted': {
|
||||
|
||||
} break;
|
||||
case 'int': {
|
||||
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
|
||||
->getNumberFormat()
|
||||
->setFormatCode('0');
|
||||
} break;
|
||||
case 'date': {
|
||||
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
|
||||
->getNumberFormat()
|
||||
->setFormatCode($this->getInjection('dateTime')->getDateFormat());
|
||||
} break;
|
||||
case 'datetime': {
|
||||
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
|
||||
->getNumberFormat()
|
||||
->setFormatCode($this->getInjection('dateTime')->getDateTimeFormat());
|
||||
} break;
|
||||
case 'datetimeOptional': {
|
||||
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
|
||||
->getNumberFormat()
|
||||
->setFormatCode($this->getInjection('dateTime')->getDateTimeFormat());
|
||||
} break;
|
||||
default: {
|
||||
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
|
||||
->getNumberFormat()
|
||||
->setFormatCode('@');
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$linkStyle = [
|
||||
'font' => [
|
||||
'color' => ['rgb' => '345b7c'],
|
||||
'underline' => 'single'
|
||||
]
|
||||
];
|
||||
foreach ($linkColList as $linkColumn) {
|
||||
$sheet->getStyle($linkColumn.$startingRowNumber.':'.$linkColumn.$rowNumber)->applyFromArray($linkStyle);
|
||||
}
|
||||
|
||||
$objWriter = \PHPExcel_IOFactory::createWriter($phpExcel, 'Excel2007');
|
||||
|
||||
if (!$this->getInjection('fileManager')->isDir('data/cache/')) {
|
||||
$this->getInjection('fileManager')->mkdir('data/cache/');
|
||||
}
|
||||
$tempFileName = 'data/cache/' . 'export_' . substr(md5(rand()), 0, 7);
|
||||
|
||||
$objWriter->save($tempFileName);
|
||||
$fp = fopen($tempFileName, 'r');
|
||||
$xlsx = stream_get_contents($fp);
|
||||
$this->getInjection('fileManager')->unlink($tempFileName);
|
||||
|
||||
return $xlsx;
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,11 @@ class ExtensionManager extends Upgrades\Base
|
||||
'after' => 'AfterInstall',
|
||||
'beforeUninstall' => 'BeforeUninstall',
|
||||
'afterUninstall' => 'AfterUninstall',
|
||||
),
|
||||
|
||||
'customDirNames' => array(
|
||||
'before' => 'beforeInstallFiles',
|
||||
'after' => 'afterInstallFiles',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\ArrayGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class IncludesType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value') || !is_array($item->value)) {
|
||||
throw new Error('Value for \'Array\\Includses\' item is not array.');
|
||||
}
|
||||
if (count($item->value) < 2) {
|
||||
throw new Error('Bad arguments passed to \'Array\\Includses\'.');
|
||||
}
|
||||
$list = $this->evaluate($item->value[0]);
|
||||
$needle = $this->evaluate($item->value[1]);
|
||||
|
||||
if (!is_array($list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($needle, $list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\DateTimeGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class DateType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$this->addDependency('dateTime');
|
||||
}
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$value = $this->evaluate($item->value[0]);
|
||||
|
||||
if (empty($value)) return 0;
|
||||
|
||||
if (strlen($value) > 11) {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'D');
|
||||
} else {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDate($value, 'D');
|
||||
}
|
||||
|
||||
return intval($resultString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\DateTimeGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class DayOfWeekType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$this->addDependency('dateTime');
|
||||
}
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$value = $this->evaluate($item->value[0]);
|
||||
|
||||
if (empty($value)) return -1;
|
||||
|
||||
if (strlen($value) > 11) {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'e');
|
||||
} else {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDate($value, 'e');
|
||||
}
|
||||
|
||||
$result = intval($resultString);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\DateTimeGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class HourType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$this->addDependency('dateTime');
|
||||
}
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$value = $this->evaluate($item->value[0]);
|
||||
|
||||
if (empty($value)) return -1;
|
||||
|
||||
if (strlen($value) > 11) {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'H');
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return intval($resultString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\DateTimeGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class MinuteType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$this->addDependency('dateTime');
|
||||
}
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$value = $this->evaluate($item->value[0]);
|
||||
|
||||
if (empty($value)) return -1;
|
||||
|
||||
if (strlen($value) > 11) {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'm');
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return intval($resultString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\DateTimeGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class MonthType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$this->addDependency('dateTime');
|
||||
}
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$value = $this->evaluate($item->value[0]);
|
||||
|
||||
if (empty($value)) return 0;
|
||||
|
||||
if (strlen($value) > 11) {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'M');
|
||||
} else {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDate($value, 'M');
|
||||
}
|
||||
|
||||
return intval($resultString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\DateTimeGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class YearType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$this->addDependency('dateTime');
|
||||
}
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$value = $this->evaluate($item->value[0]);
|
||||
|
||||
if (empty($value)) return 0;
|
||||
|
||||
if (strlen($value) > 11) {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'YYYY');
|
||||
} else {
|
||||
$resultString = $this->getInjection('dateTime')->convertSystemDate($value, 'YYYY');
|
||||
}
|
||||
|
||||
return intval($resultString);
|
||||
}
|
||||
}
|
||||
54
application/Espo/Core/Formula/Functions/ListType.php
Normal file
54
application/Espo/Core/Formula/Functions/ListType.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class ListType extends Base
|
||||
{
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($item->value as $item) {
|
||||
$result[] = $this->evaluate($item);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -219,6 +219,11 @@ class Parser
|
||||
$firstOperator = null;
|
||||
$minIndex = null;
|
||||
|
||||
if ($expression === '') return (object) [
|
||||
'type' => 'value',
|
||||
'value' => null
|
||||
];
|
||||
|
||||
foreach ($this->priorityList as $operationList) {
|
||||
foreach ($operationList as $operator) {
|
||||
$index = strpos($expression, $operator, 1);
|
||||
@@ -235,6 +240,18 @@ class Parser
|
||||
!empty($this->operatorMap[$possibleRightOperator])
|
||||
) continue;
|
||||
|
||||
$possibleLeftOperator = null;
|
||||
if (strlen($operator) === 1) {
|
||||
if ($index > 0) {
|
||||
$possibleLeftOperator = trim($expression[$index - 1] . $operator);
|
||||
}
|
||||
}
|
||||
if (
|
||||
$possibleLeftOperator &&
|
||||
$possibleLeftOperator != $operator &&
|
||||
!empty($this->operatorMap[$possibleLeftOperator])
|
||||
) continue;
|
||||
|
||||
$firstPart = substr($expression, 0, $index);
|
||||
$secondPart = substr($expression, $index + strlen($operator));
|
||||
|
||||
|
||||
@@ -117,6 +117,9 @@ class Htmlizer
|
||||
if ($item instanceof \StdClass) {
|
||||
$v = get_object_vars($v);
|
||||
}
|
||||
if (!is_array($v)) {
|
||||
$v = [];
|
||||
}
|
||||
foreach ($v as $k => $w) {
|
||||
$v[$k] = $this->format($v[$k]);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,17 @@ abstract class Injectable implements \Espo\Core\Interfaces\Injectable
|
||||
{
|
||||
}
|
||||
|
||||
public function __call($methodName, $args)
|
||||
{
|
||||
if (strpos($methodName, 'get') === 0) {
|
||||
$injectionName = lcfirst(substr($methodName, 3));
|
||||
if (in_array($injectionName, $this->dependencyList)) {
|
||||
return $this->getInjection($injectionName);
|
||||
}
|
||||
}
|
||||
throw new \BadMethodCallException('Method ' . $methodName . ' does not exist');
|
||||
}
|
||||
|
||||
protected function getInjection($name)
|
||||
{
|
||||
return $this->injections[$name];
|
||||
|
||||
59
application/Espo/Core/Loaders/Log.php
Normal file
59
application/Espo/Core/Loaders/Log.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Loaders;
|
||||
|
||||
class Log extends Base
|
||||
{
|
||||
public function load()
|
||||
{
|
||||
$config = $this->getContainer()->get('config');
|
||||
|
||||
$path = $config->get('logger.path', 'data/logs/espo.log');
|
||||
$rotation = $config->get('logger.rotation', true);
|
||||
|
||||
$log = new \Espo\Core\Utils\Log('Espo');
|
||||
$levelCode = $log->getLevelCode($config->get('logger.level', 'WARNING'));
|
||||
|
||||
if ($rotation) {
|
||||
$maxFileNumber = $config->get('logger.maxFileNumber', 30);
|
||||
$handler = new \Espo\Core\Utils\Log\Monolog\Handler\RotatingFileHandler($path, $maxFileNumber, $levelCode);
|
||||
} else {
|
||||
$handler = new \Espo\Core\Utils\Log\Monolog\Handler\StreamHandler($path, $levelCode);
|
||||
}
|
||||
$log->pushHandler($handler);
|
||||
|
||||
$errorHandler = new \Monolog\ErrorHandler($log);
|
||||
$errorHandler->registerExceptionHandler(null, false);
|
||||
$errorHandler->registerErrorHandler(array(), false);
|
||||
|
||||
return $log;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,11 +314,10 @@ class Importer
|
||||
$email->set('parentId', $contact->get('accountId'));
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$email->set('parentType', 'Contact');
|
||||
$email->set('parentId', $contact->id);
|
||||
return true;
|
||||
}
|
||||
$email->set('parentType', 'Contact');
|
||||
$email->set('parentId', $contact->id);
|
||||
return true;
|
||||
} else {
|
||||
$account = $this->getEntityManager()->getRepository('Account')->where(array(
|
||||
'emailAddress' => $emailAddress
|
||||
|
||||
@@ -47,6 +47,8 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
|
||||
private $restoreData = null;
|
||||
|
||||
protected $hooksDisabled = false;
|
||||
|
||||
protected function addDependency($name)
|
||||
{
|
||||
$this->dependencies[] = $name;
|
||||
@@ -172,7 +174,9 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
protected function beforeRemove(Entity $entity, array $options = array())
|
||||
{
|
||||
parent::beforeRemove($entity, $options);
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'beforeRemove', $entity, $options);
|
||||
if (!$this->hooksDisabled) {
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'beforeRemove', $entity, $options);
|
||||
}
|
||||
|
||||
$nowString = date('Y-m-d H:i:s', time());
|
||||
if ($entity->hasAttribute('modifiedAt')) {
|
||||
@@ -186,25 +190,25 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
protected function afterRemove(Entity $entity, array $options = array())
|
||||
{
|
||||
parent::afterRemove($entity, $options);
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterRemove', $entity, $options);
|
||||
if (!$this->hooksDisabled) {
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterRemove', $entity, $options);
|
||||
}
|
||||
}
|
||||
|
||||
protected function afterMassRelate(Entity $entity, $relationName, array $params = array(), array $options = array())
|
||||
{
|
||||
$hookData = array(
|
||||
'relationName' => $relationName,
|
||||
'relationParams' => $params
|
||||
);
|
||||
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterMassRelate', $entity, $options, $hookData);
|
||||
if (!$this->hooksDisabled) {
|
||||
$hookData = array(
|
||||
'relationName' => $relationName,
|
||||
'relationParams' => $params
|
||||
);
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterMassRelate', $entity, $options, $hookData);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(Entity $entity, array $options = array())
|
||||
{
|
||||
$result = parent::remove($entity, $options);
|
||||
if ($result) {
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterRemove', $entity, $options);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -214,12 +218,14 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
|
||||
if ($foreign instanceof Entity) {
|
||||
$foreignEntity = $foreign;
|
||||
$hookData = array(
|
||||
'relationName' => $relationName,
|
||||
'relationData' => $data,
|
||||
'foreignEntity' => $foreignEntity
|
||||
);
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterRelate', $entity, $options, $hookData);
|
||||
if (!$this->hooksDisabled) {
|
||||
$hookData = array(
|
||||
'relationName' => $relationName,
|
||||
'relationData' => $data,
|
||||
'foreignEntity' => $foreignEntity
|
||||
);
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterRelate', $entity, $options, $hookData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,11 +235,13 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
|
||||
if ($foreign instanceof Entity) {
|
||||
$foreignEntity = $foreign;
|
||||
$hookData = array(
|
||||
'relationName' => $relationName,
|
||||
'foreignEntity' => $foreignEntity
|
||||
);
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterUnrelate', $entity, $options, $hookData);
|
||||
if (!$this->hooksDisabled) {
|
||||
$hookData = array(
|
||||
'relationName' => $relationName,
|
||||
'foreignEntity' => $foreignEntity
|
||||
);
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterUnrelate', $entity, $options, $hookData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +249,9 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
{
|
||||
parent::beforeSave($entity, $options);
|
||||
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'beforeSave', $entity, $options);
|
||||
if (!$this->hooksDisabled) {
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'beforeSave', $entity, $options);
|
||||
}
|
||||
}
|
||||
|
||||
protected function afterSave(Entity $entity, array $options = array())
|
||||
@@ -257,7 +267,9 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
$this->processSpecifiedRelationsSave($entity);
|
||||
$this->processFileFieldsSave($entity);
|
||||
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterSave', $entity, $options);
|
||||
if (!$this->hooksDisabled) {
|
||||
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterSave', $entity, $options);
|
||||
}
|
||||
}
|
||||
|
||||
public function save(Entity $entity, array $options = array())
|
||||
@@ -279,18 +291,22 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
$entity->set('modifiedAt', $nowString);
|
||||
}
|
||||
if ($entity->hasAttribute('createdById')) {
|
||||
if (empty($options['import']) || !$entity->has('createdById')) {
|
||||
$entity->set('createdById', $this->getEntityManager()->getUser()->id);
|
||||
if (empty($options['skipCreatedBy']) && (empty($options['import']) || !$entity->has('createdById'))) {
|
||||
if ($this->getEntityManager()->getUser()) {
|
||||
$entity->set('createdById', $this->getEntityManager()->getUser()->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (empty($options['silent'])) {
|
||||
if (empty($options['silent']) && empty($options['skipModifiedBy'])) {
|
||||
if ($entity->hasAttribute('modifiedAt')) {
|
||||
$entity->set('modifiedAt', $nowString);
|
||||
}
|
||||
if ($entity->hasAttribute('modifiedById')) {
|
||||
$entity->set('modifiedById', $this->getEntityManager()->getUser()->id);
|
||||
$entity->set('modifiedByName', $this->getEntityManager()->getUser()->get('name'));
|
||||
if ($this->getEntityManager()->getUser()) {
|
||||
$entity->set('modifiedById', $this->getEntityManager()->getUser()->id);
|
||||
$entity->set('modifiedByName', $this->getEntityManager()->getUser()->get('name'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -401,8 +417,16 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
|
||||
} else {
|
||||
if (!empty($columns)) {
|
||||
foreach ($columns as $columnName => $columnField) {
|
||||
if (isset($columnData->$id)) {
|
||||
if ($columnData->$id->$columnName !== $existingColumnsData->$id->$columnName) {
|
||||
if (isset($columnData->$id) && is_object($columnData->$id)) {
|
||||
if (
|
||||
property_exists($columnData->$id, $columnName)
|
||||
&&
|
||||
(
|
||||
!property_exists($existingColumnsData->$id, $columnName)
|
||||
||
|
||||
$columnData->$id->$columnName !== $existingColumnsData->$id->$columnName
|
||||
)
|
||||
) {
|
||||
$toUpdateIds[] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ class AclManager extends \Espo\Core\AclManager
|
||||
$config = $this->getContainer()->get('config');
|
||||
$fileManager = $this->getContainer()->get('fileManager');
|
||||
$metadata = $this->getContainer()->get('metadata');
|
||||
$fieldManager = $this->getContainer()->get('fieldManager');
|
||||
$fieldManager = $this->getContainer()->get('fieldManagerUtil');
|
||||
$portal = $this->getPortal();
|
||||
|
||||
$this->tableHashMap[$key] = new $this->tableClassName($user, $portal, $config, $fileManager, $metadata, $fieldManager);
|
||||
|
||||
@@ -47,7 +47,7 @@ class ThemeManager extends \Espo\Core\Utils\ThemeManager
|
||||
{
|
||||
$theme = $this->portal->get('theme');
|
||||
if (!$theme) {
|
||||
$theme = $this->defaultName;
|
||||
$theme = $this->config->get('theme', $this->defaultName);
|
||||
}
|
||||
return $theme;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,20 @@ class Event extends \Espo\Core\ORM\Repositories\RDB
|
||||
{
|
||||
protected $reminderDateAttribute = 'dateStart';
|
||||
|
||||
protected $reminderSkippingStatusList = ['Held', 'Not Held'];
|
||||
|
||||
protected function beforeSave(Entity $entity, array $options = array())
|
||||
{
|
||||
if ($entity->isAttributeChanged('status') && in_array($entity->get('status'), $this->reminderSkippingStatusList)) {
|
||||
$entity->set('reminders', []);
|
||||
}
|
||||
parent::beforeSave($entity, $options);
|
||||
}
|
||||
|
||||
protected function afterRemove(Entity $entity, array $options = array())
|
||||
{
|
||||
parent::afterRemove($entity, $options);
|
||||
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
$sql = "
|
||||
DELETE FROM `reminder`
|
||||
|
||||
@@ -130,7 +130,7 @@ class Base
|
||||
|
||||
$result['orderBy'] = $sortBy;
|
||||
$type = $this->getMetadata()->get(['entityDefs', $this->getEntityType(), 'fields', $sortBy, 'type']);
|
||||
if ($type === 'link') {
|
||||
if (in_array($type, ['link', 'file', 'image'])) {
|
||||
$result['orderBy'] .= 'Name';
|
||||
} else if ($type === 'linkParent') {
|
||||
$result['orderBy'] .= 'Type';
|
||||
@@ -188,6 +188,8 @@ class Base
|
||||
|
||||
$whereClause = array();
|
||||
foreach ($where as $item) {
|
||||
if (!isset($item['type'])) continue;
|
||||
|
||||
if ($item['type'] == 'bool' && !empty($item['value']) && is_array($item['value'])) {
|
||||
foreach ($item['value'] as $filter) {
|
||||
$p = $this->getBoolFilterWhere($filter);
|
||||
@@ -210,6 +212,8 @@ class Base
|
||||
|
||||
$additionalFilters = array();
|
||||
foreach ($where as $item) {
|
||||
if (!isset($item['type'])) continue;
|
||||
|
||||
$type = $item['type'];
|
||||
if (!in_array($type, $ignoreTypeList)) {
|
||||
$part = $this->getWherePart($item, $result);
|
||||
@@ -985,6 +989,7 @@ class Base
|
||||
switch ($item['type']) {
|
||||
case 'or':
|
||||
case 'and':
|
||||
case 'not':
|
||||
if (is_array($item['value'])) {
|
||||
$arr = array();
|
||||
foreach ($item['value'] as $i) {
|
||||
@@ -1030,7 +1035,7 @@ class Base
|
||||
$part[$attribute . '>='] = $item['value'];
|
||||
break;
|
||||
case 'lessThanOrEquals':
|
||||
$part[$attribute . '<'] = $item['value'];
|
||||
$part[$attribute . '<='] = $item['value'];
|
||||
break;
|
||||
case 'in':
|
||||
$part[$attribute . '='] = $item['value'];
|
||||
@@ -1161,16 +1166,49 @@ class Base
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'columnLike':
|
||||
case 'columnIn':
|
||||
case 'columnIsNull':
|
||||
case 'columnNotIn':
|
||||
$link = $this->getMetadata()->get(['entityDefs', $this->entityType, 'fields', $attribute, 'link']);
|
||||
$column = $this->getMetadata()->get(['entityDefs', $this->entityType, 'fields', $attribute, 'column']);
|
||||
$alias = $link . 'Filter' . strval(rand(10000, 99999));
|
||||
$this->setDistinct(true, $result);
|
||||
$this->addLeftJoin([$link, $alias], $result);
|
||||
$value = $item['value'];
|
||||
$columnKey = $alias . 'Middle.' . $column;
|
||||
if ($item['type'] === 'columnIn') {
|
||||
$part[$columnKey] = $value;
|
||||
} else if ($item['type'] === 'columnNotIn') {
|
||||
$part[$columnKey . '!='] = $value;
|
||||
} else if ($item['type'] === 'columnIsNull') {
|
||||
$part[$columnKey] = null;
|
||||
} else if ($item['type'] === 'columnIsNotNull') {
|
||||
$part[$columnKey . '!='] = null;
|
||||
} else if ($item['type'] === 'columnLike') {
|
||||
$part[$columnKey . '*'] = $value;
|
||||
} else if ($item['type'] === 'columnStartsWith') {
|
||||
$part[$columnKey . '*'] = $value . '%';
|
||||
} else if ($item['type'] === 'columnEndsWith') {
|
||||
$part[$columnKey . '*'] = '%' . $value;
|
||||
} else if ($item['type'] === 'columnContains') {
|
||||
$part[$columnKey . '*'] = '%' . $value . '%';
|
||||
} else if ($item['type'] === 'columnEquals') {
|
||||
$part[$columnKey . '='] = $value;
|
||||
} else if ($item['type'] === 'columnNotEquals') {
|
||||
$part[$columnKey . '!='] = $value;
|
||||
}
|
||||
break;
|
||||
case 'isNotLinked':
|
||||
if (!$result) break;
|
||||
$alias = $attribute . 'IsNotLinkedFilter' . strval(rand(10000, 99999));;
|
||||
$alias = $attribute . 'IsNotLinkedFilter' . strval(rand(10000, 99999));
|
||||
$part[$alias . '.id'] = null;
|
||||
$this->setDistinct(true, $result);
|
||||
$this->addLeftJoin([$attribute, $alias], $result);
|
||||
break;
|
||||
case 'isLinked':
|
||||
if (!$result) break;
|
||||
$alias = $attribute . 'IsLinkedFilter' . strval(rand(10000, 99999));;
|
||||
$alias = $attribute . 'IsLinkedFilter' . strval(rand(10000, 99999));
|
||||
$part[$alias . '.id!='] = null;
|
||||
$this->setDistinct(true, $result);
|
||||
$this->addLeftJoin([$attribute, $alias], $result);
|
||||
|
||||
5
application/Espo/Core/Templates/i18n/en_GB/Base.json
Normal file
5
application/Espo/Core/Templates/i18n/en_GB/Base.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Create {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
10
application/Espo/Core/Templates/i18n/en_GB/BasePlus.json
Normal file
10
application/Espo/Core/Templates/i18n/en_GB/BasePlus.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Create {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
15
application/Espo/Core/Templates/i18n/en_GB/Company.json
Normal file
15
application/Espo/Core/Templates/i18n/en_GB/Company.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"fields": {
|
||||
"billingAddress": "Billing Address",
|
||||
"shippingAddress": "Shipping Address",
|
||||
"website": "Website"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Create {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
36
application/Espo/Core/Templates/i18n/en_GB/Event.json
Normal file
36
application/Espo/Core/Templates/i18n/en_GB/Event.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"fields": {
|
||||
"parent": "Parent",
|
||||
"dateStart": "Date Start",
|
||||
"dateEnd": "Date End",
|
||||
"duration": "Duration",
|
||||
"status": "Status",
|
||||
"reminders": "Reminders"
|
||||
},
|
||||
"links": {
|
||||
"parent": "Parent"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Planned",
|
||||
"Held": "Held",
|
||||
"Not Held": "Not Held"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Create {entityTypeTranslated}",
|
||||
"Schedule {entityType}": "Schedule {entityTypeTranslated}",
|
||||
"Log {entityType}": "Log {entityTypeTranslated}",
|
||||
"Set Held": "Set Held",
|
||||
"Set Not Held": "Set Not Held"
|
||||
},
|
||||
"massActions": {
|
||||
"setHeld": "Set Held",
|
||||
"setNotHeld": "Set Not Held"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Planned",
|
||||
"held": "Held",
|
||||
"todays": "Today's"
|
||||
}
|
||||
}
|
||||
13
application/Espo/Core/Templates/i18n/en_GB/Person.json
Normal file
13
application/Espo/Core/Templates/i18n/en_GB/Person.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"fields": {
|
||||
"address": "Address"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Create {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
5
application/Espo/Core/Templates/i18n/es_MX/Base.json
Normal file
5
application/Espo/Core/Templates/i18n/es_MX/Base.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Crear {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
10
application/Espo/Core/Templates/i18n/es_MX/BasePlus.json
Normal file
10
application/Espo/Core/Templates/i18n/es_MX/BasePlus.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"links": {
|
||||
"meetings": "Juntas",
|
||||
"calls": "Llamadas",
|
||||
"tasks": "Tareas"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Crear {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
15
application/Espo/Core/Templates/i18n/es_MX/Company.json
Normal file
15
application/Espo/Core/Templates/i18n/es_MX/Company.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"fields": {
|
||||
"billingAddress": "Dirección de Facturación",
|
||||
"shippingAddress": "Dirección de envio",
|
||||
"website": "Sitio Web"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "reuniones",
|
||||
"calls": "Llamadas",
|
||||
"tasks": "Tareas"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Crear {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
36
application/Espo/Core/Templates/i18n/es_MX/Event.json
Normal file
36
application/Espo/Core/Templates/i18n/es_MX/Event.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"fields": {
|
||||
"parent": "Padre",
|
||||
"dateStart": "Fecha de incio",
|
||||
"dateEnd": "Fecha final",
|
||||
"duration": "Duracion",
|
||||
"status": "Estátus",
|
||||
"reminders": "Recordatorios"
|
||||
},
|
||||
"links": {
|
||||
"parent": "Padre"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Planeado",
|
||||
"Held": "Retenidas",
|
||||
"Not Held": "Pendientes"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Creat",
|
||||
"Schedule {entityType}": "Agendar {entityTypeTranslated}",
|
||||
"Log {entityType}": "Registrar {entityTypeTranslated}",
|
||||
"Set Held": "Marcar como Retenida",
|
||||
"Set Not Held": "Marcar como Pendiente"
|
||||
},
|
||||
"massActions": {
|
||||
"setHeld": "Marcar como Retenida",
|
||||
"setNotHeld": "Marcar como Pendiente"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Planeado",
|
||||
"held": "Retenida",
|
||||
"todays": "Hoy"
|
||||
}
|
||||
}
|
||||
13
application/Espo/Core/Templates/i18n/es_MX/Person.json
Normal file
13
application/Espo/Core/Templates/i18n/es_MX/Person.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"fields": {
|
||||
"address": "Dirección"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Reuniones",
|
||||
"calls": "Llamadas",
|
||||
"tasks": "Tareas"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Crear {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,15 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
"fields": {
|
||||
"billingAddress": "Billing Address",
|
||||
"shippingAddress": "Shipping Address",
|
||||
"website": "Website"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,36 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
"fields": {
|
||||
"parent": "Parent",
|
||||
"dateStart": "Date de début",
|
||||
"dateEnd": "Date End",
|
||||
"duration": "Duration",
|
||||
"status": "Status",
|
||||
"reminders": "Reminders"
|
||||
},
|
||||
"links": {
|
||||
"parent": "Parent"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Planned",
|
||||
"Held": "Held",
|
||||
"Not Held": "Not Held"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}",
|
||||
"Schedule {entityType}": "Schedule {entityTypeTranslated}",
|
||||
"Log {entityType}": "Log {entityTypeTranslated}",
|
||||
"Set Held": "Set Held",
|
||||
"Set Not Held": "Set Not Held"
|
||||
},
|
||||
"massActions": {
|
||||
"setHeld": "Set Held",
|
||||
"setNotHeld": "Set Not Held"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Planned",
|
||||
"held": "Held",
|
||||
"todays": "Today's"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
"fields": {
|
||||
"address": "Address"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Créer un {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,15 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
"fields": {
|
||||
"billingAddress": "Платежный адрес",
|
||||
"shippingAddress": "Адрес доставки",
|
||||
"website": "Website"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,36 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
"fields": {
|
||||
"parent": "Parent",
|
||||
"dateStart": "Date Start",
|
||||
"dateEnd": "Date End",
|
||||
"duration": "Duration",
|
||||
"status": "Status",
|
||||
"reminders": "Reminders"
|
||||
},
|
||||
"links": {
|
||||
"parent": "Parent"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Planned",
|
||||
"Held": "Held",
|
||||
"Not Held": "Not Held"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}",
|
||||
"Schedule {entityType}": "Schedule {entityTypeTranslated}",
|
||||
"Log {entityType}": "Log {entityTypeTranslated}",
|
||||
"Set Held": "Set Held",
|
||||
"Set Not Held": "Set Not Held"
|
||||
},
|
||||
"massActions": {
|
||||
"setHeld": "Set Held",
|
||||
"setNotHeld": "Set Not Held"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Запланировано",
|
||||
"held": "Held",
|
||||
"todays": "Сегодняшние"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
"fields": {
|
||||
"address": "Адрес"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Создать {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
5
application/Espo/Core/Templates/i18n/sr_RS/Base.json
Normal file
5
application/Espo/Core/Templates/i18n/sr_RS/Base.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create {entityType}": "Napravi {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
10
application/Espo/Core/Templates/i18n/sr_RS/BasePlus.json
Normal file
10
application/Espo/Core/Templates/i18n/sr_RS/BasePlus.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"links": {
|
||||
"meetings": "Sastanci",
|
||||
"calls": "Pozivi",
|
||||
"tasks": "Zadaci"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Napravi {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
15
application/Espo/Core/Templates/i18n/sr_RS/Company.json
Normal file
15
application/Espo/Core/Templates/i18n/sr_RS/Company.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"fields": {
|
||||
"billingAddress": "Adresa za naplatu",
|
||||
"shippingAddress": "Adresa za dostavu",
|
||||
"website": "Sajt"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Sastanci",
|
||||
"calls": "Pozivi",
|
||||
"tasks": "Zadaci"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Napravi {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
36
application/Espo/Core/Templates/i18n/sr_RS/Event.json
Normal file
36
application/Espo/Core/Templates/i18n/sr_RS/Event.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"fields": {
|
||||
"parent": "Roditelj",
|
||||
"dateStart": "Početni datum",
|
||||
"dateEnd": "Krajnji datum",
|
||||
"duration": "Trajanje",
|
||||
"status": "Status",
|
||||
"reminders": "Podsetnici"
|
||||
},
|
||||
"links": {
|
||||
"parent": "Roditelj"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Planiran",
|
||||
"Held": "Održan",
|
||||
"Not Held": "Nije održan"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Napravi {entityTypeTranslated}",
|
||||
"Schedule {entityType}": "Zakaži {entityTypeTranslated}",
|
||||
"Log {entityType}": "Zabeleži {entitiTipeTranslated}",
|
||||
"Set Held": "Postavi kao održano",
|
||||
"Set Not Held": "Postavi kao nije održano"
|
||||
},
|
||||
"massActions": {
|
||||
"setHeld": "Postavi kao održano",
|
||||
"setNotHeld": "Postavi kao nije održano"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Planiran",
|
||||
"held": "Održan",
|
||||
"todays": "Današnji"
|
||||
}
|
||||
}
|
||||
13
application/Espo/Core/Templates/i18n/sr_RS/Person.json
Normal file
13
application/Espo/Core/Templates/i18n/sr_RS/Person.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"fields": {
|
||||
"address": "Adresa"
|
||||
},
|
||||
"links": {
|
||||
"meetings": "Sastanci",
|
||||
"calls": "Pozivi",
|
||||
"tasks": "Zadaci"
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Napravi {entityTypeTranslated}"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"fields": {
|
||||
"billingAddress": "Billing Address",
|
||||
"billingAddress": "Адреса виставлення рахунку",
|
||||
"shippingAddress": "Адреса доставки",
|
||||
"website": "Вебсайт"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"fields": {
|
||||
"parent": "Джерело",
|
||||
"parent": "Батько",
|
||||
"dateStart": "Дата початку",
|
||||
"dateEnd": "Дата завершення",
|
||||
"duration": "Тривалість",
|
||||
@@ -8,29 +8,29 @@
|
||||
"reminders": "Нагадування"
|
||||
},
|
||||
"links": {
|
||||
"parent": "Джерело"
|
||||
"parent": "Батько"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Плановий",
|
||||
"Held": "Вміщений",
|
||||
"Held": "Виконано",
|
||||
"Not Held": "Не вміщений"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create {entityType}": "Створити {entityTypeTranslated}",
|
||||
"Schedule {entityType}": "Розклад {entityTypeTranslated} ",
|
||||
"Log {entityType}": "Log {entityTypeTranslated}",
|
||||
"Set Held": "Set Held",
|
||||
"Set Not Held": "Set Not Held"
|
||||
"Log {entityType}": "Лог {entityTypeTranslated}",
|
||||
"Set Held": "Позначити виконаним",
|
||||
"Set Not Held": "Позначити невиконаним"
|
||||
},
|
||||
"massActions": {
|
||||
"setHeld": "Set Held",
|
||||
"setNotHeld": "Set Not Held"
|
||||
"setHeld": "Позначити виконаними",
|
||||
"setNotHeld": "Позначити невиконаними"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Планований",
|
||||
"held": "Вміщений ",
|
||||
"held": "Виконані",
|
||||
"todays": "Сьогоднішні"
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,11 @@ class UpgradeManager extends Upgrades\Base
|
||||
'scriptNames' => array(
|
||||
'before' => 'BeforeUpgrade',
|
||||
'after' => 'AfterUpgrade',
|
||||
),
|
||||
|
||||
'customDirNames' => array(
|
||||
'before' => 'beforeUpgradeFiles',
|
||||
'after' => 'afterUpgradeFiles',
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -389,9 +389,7 @@ abstract class Base
|
||||
{
|
||||
if (!isset($this->data['fileList'])) {
|
||||
$packagePath = $this->getPackagePath();
|
||||
$filesPath = Util::concatPath($packagePath, self::FILES);
|
||||
|
||||
$this->data['fileList'] = $this->getFileManager()->getFileList($filesPath, true, '', true, true);
|
||||
$this->data['fileList'] = $this->getFileList($packagePath);
|
||||
}
|
||||
|
||||
return $this->data['fileList'];
|
||||
@@ -401,14 +399,55 @@ abstract class Base
|
||||
{
|
||||
if (!isset($this->data['restoreFileList'])) {
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
$backupFilePath = Util::concatPath($backupPath, self::FILES);
|
||||
|
||||
$this->data['restoreFileList'] = $this->getFileManager()->getFileList($backupFilePath, true, '', true, true);
|
||||
$this->data['restoreFileList'] = $this->getFileList($backupPath);
|
||||
}
|
||||
|
||||
return $this->data['restoreFileList'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file directories (files, beforeInstallFiles, afterInstallFiles)
|
||||
*
|
||||
* @param sting $parentDirPath
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getFileDirs($parentDirPath = null)
|
||||
{
|
||||
$dirNames = $this->getParams('customDirNames');
|
||||
$paths = array(self::FILES, $dirNames['before'], $dirNames['after']);
|
||||
|
||||
if (isset($parentDirPath)) {
|
||||
foreach ($paths as &$path) {
|
||||
$path = Util::concatPath($parentDirPath, $path);
|
||||
}
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file list from directories: files, beforeUpgradeFiles, afterUpgradeFiles
|
||||
*
|
||||
* @param string $dirPath
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getFileList($dirPath)
|
||||
{
|
||||
$fileList = array();
|
||||
|
||||
$paths = $this->getFileDirs($dirPath);
|
||||
foreach ($paths as $filesPath) {
|
||||
if (file_exists($filesPath)) {
|
||||
$files = $this->getFileManager()->getFileList($filesPath, true, '', true, true);
|
||||
$fileList = array_merge($fileList, $files);
|
||||
}
|
||||
}
|
||||
|
||||
return $fileList;
|
||||
}
|
||||
|
||||
protected function copy($sourcePath, $destPath, $recursively = false, array $fileList = null, $copyOnlyFiles = false)
|
||||
{
|
||||
try {
|
||||
@@ -423,15 +462,32 @@ abstract class Base
|
||||
/**
|
||||
* Copy files from upgrade/extension package
|
||||
*
|
||||
* @param string $processId
|
||||
* @param string $type
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function copyFiles()
|
||||
protected function copyFiles($type = null)
|
||||
{
|
||||
$packagePath = $this->getPackagePath();
|
||||
$filesPath = Util::concatPath($packagePath, self::FILES);
|
||||
switch ($type) {
|
||||
case 'before':
|
||||
case 'after':
|
||||
$dirNames = $this->getParams('customDirNames');
|
||||
$dirPath = $dirNames[$type];
|
||||
break;
|
||||
|
||||
return $this->copy($filesPath, '', true);
|
||||
default:
|
||||
$dirPath = self::FILES;
|
||||
break;
|
||||
}
|
||||
|
||||
$packagePath = $this->getPackagePath();
|
||||
$filesPath = Util::concatPath($packagePath, $dirPath);
|
||||
|
||||
if (file_exists($filesPath)) {
|
||||
return $this->copy($filesPath, '', true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getManifest()
|
||||
|
||||
@@ -67,6 +67,11 @@ class Install extends \Espo\Core\Upgrades\Actions\Base
|
||||
|
||||
$this->backupExistingFiles();
|
||||
|
||||
//beforeInstallFiles
|
||||
if (!$this->copyFiles('before')) {
|
||||
$this->throwErrorAndRemovePackage('Cannot copy beforeInstall files.');
|
||||
}
|
||||
|
||||
/* run before install script */
|
||||
$this->runScript('before');
|
||||
|
||||
@@ -85,6 +90,11 @@ class Install extends \Espo\Core\Upgrades\Actions\Base
|
||||
$this->throwErrorAndRemovePackage('Error occurred while EspoCRM rebuild.');
|
||||
}
|
||||
|
||||
//afterInstallFiles
|
||||
if (!$this->copyFiles('after')) {
|
||||
$this->throwErrorAndRemovePackage('Cannot copy afterInstall files.');
|
||||
}
|
||||
|
||||
/* run before install script */
|
||||
$this->runScript('after');
|
||||
|
||||
@@ -112,7 +122,9 @@ class Install extends \Espo\Core\Upgrades\Actions\Base
|
||||
$deleteFileList = array_diff($copyFileList, $backupFileList);
|
||||
|
||||
$res = $this->copy($backupFilePath, '', true);
|
||||
$res &= $this->getFileManager()->remove($deleteFileList, null, true);
|
||||
if (!empty($deleteFileList)) {
|
||||
$res &= $this->getFileManager()->remove($deleteFileList, null, true);
|
||||
}
|
||||
|
||||
if ($res) {
|
||||
$this->getFileManager()->removeInDir($backupPath, true);
|
||||
|
||||
@@ -95,15 +95,20 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base
|
||||
protected function restoreFiles()
|
||||
{
|
||||
$packagePath = $this->getPath('packagePath');
|
||||
$filesPath = Util::concatPath($packagePath, self::FILES);
|
||||
|
||||
if (!file_exists($filesPath)) {
|
||||
$manifestPath = Util::concatPath($packagePath, $this->manifestName);
|
||||
if (!file_exists($manifestPath)) {
|
||||
$this->unzipArchive($packagePath);
|
||||
}
|
||||
|
||||
$res = $this->copy($filesPath, '', true);
|
||||
$fileDirs = $this->getFileDirs($packagePath);
|
||||
foreach ($fileDirs as $filesPath) {
|
||||
if (file_exists($filesPath)) {
|
||||
$res = $this->copy($filesPath, '', true);
|
||||
}
|
||||
}
|
||||
|
||||
$manifestJson = $this->getFileManager()->getContents(array($packagePath, $this->manifestName));
|
||||
$manifestJson = $this->getFileManager()->getContents($manifestPath);
|
||||
$manifest = Json::decode($manifestJson, true);
|
||||
if (!empty($manifest['delete'])) {
|
||||
$res &= $this->getFileManager()->remove($manifest['delete'], null, true);
|
||||
@@ -114,7 +119,7 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function copyFiles()
|
||||
protected function copyFiles($type = null)
|
||||
{
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
$res = $this->copy(array($backupPath, self::FILES), '', true);
|
||||
|
||||
@@ -63,9 +63,8 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install
|
||||
|
||||
/** copy scripts files */
|
||||
$packagePath = $this->getPackagePath();
|
||||
$res &= $this->copy(array($packagePath, self::SCRIPTS), array($backupPath, self::SCRIPTS), true);
|
||||
|
||||
return $res;
|
||||
return $this->copy(array($packagePath, self::SCRIPTS), array($backupPath, self::SCRIPTS), true);
|
||||
}
|
||||
|
||||
protected function isNew()
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils\Database\Orm;
|
||||
|
||||
use Espo\Core\Utils\Util;
|
||||
|
||||
class Base
|
||||
|
||||
@@ -190,8 +190,14 @@ class Converter
|
||||
|
||||
public function afterProcess(array $ormMeta)
|
||||
{
|
||||
foreach($ormMeta as $entityName => &$entityParams) {
|
||||
foreach($entityParams['fields'] as $fieldName => &$fieldParams) {
|
||||
foreach ($ormMeta as $entityName => &$entityParams) {
|
||||
foreach ($entityParams['fields'] as $fieldName => &$fieldParams) {
|
||||
|
||||
/* remove fields without type */
|
||||
if (!isset($fieldParams['type']) && (!isset($fieldParams['notStorable']) || $fieldParams['notStorable'] === false)) {
|
||||
unset($entityParams['fields'][$fieldName]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($fieldParams['type']) {
|
||||
case 'id':
|
||||
@@ -240,16 +246,16 @@ class Converter
|
||||
$outputMeta = array(
|
||||
'id' => array(
|
||||
'type' => Entity::ID,
|
||||
'dbType' => 'varchar',
|
||||
'dbType' => 'varchar'
|
||||
),
|
||||
'name' => array(
|
||||
'type' => isset($entityMeta['fields']['name']['type']) ? $entityMeta['fields']['name']['type'] : Entity::VARCHAR,
|
||||
'notStorable' => true,
|
||||
'notStorable' => true
|
||||
),
|
||||
'deleted' => array(
|
||||
'type' => Entity::BOOL,
|
||||
'default' => false,
|
||||
),
|
||||
'default' => false
|
||||
)
|
||||
);
|
||||
|
||||
foreach($entityMeta['fields'] as $fieldName => $fieldParams) {
|
||||
@@ -307,14 +313,27 @@ class Converter
|
||||
|
||||
if (class_exists($className) && method_exists($className, 'load')) {
|
||||
$helperClass = new $className($this->metadata, $ormMeta, $entityDefs);
|
||||
$fieldResult = $helperClass->process( $fieldName, $entityName );
|
||||
$fieldResult = $helperClass->process($fieldName, $entityName);
|
||||
if (isset($fieldResult['unset'])) {
|
||||
$ormMeta = Util::unsetInArray($ormMeta, $fieldResult['unset']);
|
||||
unset($fieldResult['unset']);
|
||||
}
|
||||
|
||||
$ormMeta = Util::merge($ormMeta, $fieldResult);
|
||||
}
|
||||
|
||||
$defaultAttributes = $this->metadata->get(['entityDefs', $entityName, 'fields', $fieldName, 'defaultAttributes']);
|
||||
if ($defaultAttributes && array_key_exists($fieldName, $defaultAttributes)) {
|
||||
$defaultMetadataPart = array(
|
||||
$entityName => array(
|
||||
'fields' => array(
|
||||
$fieldName => array(
|
||||
'default' => $defaultAttributes[$fieldName]
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
$ormMeta = Util::merge($ormMeta, $defaultMetadataPart);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,24 +40,27 @@ class Link extends Base
|
||||
'fields' => array(
|
||||
$fieldName.'Id' => array(
|
||||
'type' => 'foreignId',
|
||||
'index' => $fieldName,
|
||||
'index' => $fieldName
|
||||
),
|
||||
$fieldName.'Name' => array(
|
||||
'type' => 'varchar',
|
||||
'notStorable' => true,
|
||||
),
|
||||
),
|
||||
'notStorable' => true
|
||||
)
|
||||
)
|
||||
),
|
||||
'unset' => array(
|
||||
$entityName => array(
|
||||
'fields.'.$fieldName,
|
||||
),
|
||||
),
|
||||
'fields.'.$fieldName
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!empty($fieldParams['notStorable'])) {
|
||||
$data[$entityName]['fields'][$fieldName.'Id']['notStorable'] = true;
|
||||
}
|
||||
|
||||
if (!empty($fieldParams['defaultAttributes']) && array_key_exists($fieldName.'Id', $fieldParams['defaultAttributes'])) {
|
||||
$data[$entityName]['fields'][$fieldName.'Id']['default'] = $fieldParams['defaultAttributes'][$fieldName.'Id'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -33,31 +33,42 @@ class LinkParent extends Base
|
||||
{
|
||||
protected function load($fieldName, $entityName)
|
||||
{
|
||||
return array(
|
||||
$data = array(
|
||||
$entityName => array (
|
||||
'fields' => array(
|
||||
$fieldName.'Id' => array(
|
||||
'type' => 'foreignId',
|
||||
'index' => $fieldName,
|
||||
'index' => $fieldName
|
||||
),
|
||||
$fieldName.'Type' => array(
|
||||
'type' => 'foreignType',
|
||||
'notNull' => false,
|
||||
'index' => $fieldName,
|
||||
'index' => $fieldName
|
||||
),
|
||||
$fieldName.'Name' => array(
|
||||
'type' => 'varchar',
|
||||
'notStorable' => true,
|
||||
'relation' => $fieldName,
|
||||
'isParentName' => true
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
'unset' => array(
|
||||
$entityName => array(
|
||||
'fields.'.$fieldName,
|
||||
),
|
||||
),
|
||||
'fields.'.$fieldName
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$fieldParams = $this->getFieldParams();
|
||||
|
||||
if (!empty($fieldParams['defaultAttributes']) && array_key_exists($fieldName.'Id', $fieldParams['defaultAttributes'])) {
|
||||
$data[$entityName]['fields'][$fieldName.'Id']['default'] = $fieldParams['defaultAttributes'][$fieldName.'Id'];
|
||||
}
|
||||
if (!empty($fieldParams['defaultAttributes']) && array_key_exists($fieldName.'Type', $fieldParams['defaultAttributes'])) {
|
||||
$data[$entityName]['fields'][$fieldName.'Type']['default'] = $fieldParams['defaultAttributes'][$fieldName.'Type'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -440,13 +440,13 @@ class Converter
|
||||
|
||||
$dependentEntities[] = $entityName;
|
||||
|
||||
foreach ($ormMeta[$entityName]['relations'] as $relationName => $relationParams) {
|
||||
|
||||
if (isset($relationParams['entity'])) {
|
||||
$relationEntity = $relationParams['entity'];
|
||||
|
||||
if (!in_array($relationEntity, $dependentEntities)) {
|
||||
$dependentEntities = $this->getDependentEntities($relationEntity, $ormMeta, $dependentEntities);
|
||||
if (array_key_exists('relations', $ormMeta[$entityName])) {
|
||||
foreach ($ormMeta[$entityName]['relations'] as $relationName => $relationParams) {
|
||||
if (isset($relationParams['entity'])) {
|
||||
$relationEntity = $relationParams['entity'];
|
||||
if (!in_array($relationEntity, $dependentEntities)) {
|
||||
$dependentEntities = $this->getDependentEntities($relationEntity, $ormMeta, $dependentEntities);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,16 @@ class DateTime
|
||||
$this->timezone = new \DateTimeZone($timeZone);
|
||||
}
|
||||
|
||||
public function getDateFormat()
|
||||
{
|
||||
return $this->dateFormat;
|
||||
}
|
||||
|
||||
public function getDateTimeFormat()
|
||||
{
|
||||
return $this->dateFormat . ' ' . $this->timeFormat;
|
||||
}
|
||||
|
||||
public function getInternalDateTimeFormat()
|
||||
{
|
||||
return $this->internalDateTimeFormat;
|
||||
|
||||
@@ -49,7 +49,7 @@ class EntityManager
|
||||
|
||||
private $container;
|
||||
|
||||
private $reservedWordList = ['__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor'];
|
||||
private $reservedWordList = ['__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor', 'common'];
|
||||
|
||||
public function __construct(Metadata $metadata, Language $language, File\Manager $fileManager, Config $config, Container $container = null)
|
||||
{
|
||||
@@ -102,6 +102,26 @@ class EntityManager
|
||||
return $this->container->get('serviceFactory');
|
||||
}
|
||||
|
||||
protected function checkControllerExists($name)
|
||||
{
|
||||
$controllerClassName = '\\Espo\\Custom\\Controllers\\' . Util::normilizeClassName($name);
|
||||
if (class_exists($controllerClassName)) {
|
||||
return true;
|
||||
} else {
|
||||
foreach ($this->getMetadata()->getModuleList() as $moduleName) {
|
||||
$controllerClassName = '\\Espo\\Modules\\' . $moduleName . '\\Controllers\\' . Util::normilizeClassName($name);
|
||||
if (class_exists($controllerClassName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$controllerClassName = '\\Espo\\Controllers\\' . Util::normilizeClassName($name);
|
||||
if (class_exists($controllerClassName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function create($name, $type, $params = array())
|
||||
{
|
||||
$name = ucfirst($name);
|
||||
@@ -114,6 +134,10 @@ class EntityManager
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if ($this->checkControllerExists($name)) {
|
||||
throw new Conflict('Entity name \''.$name.'\' is not allowed.');
|
||||
}
|
||||
|
||||
$serviceFactory = $this->getServiceFactory();
|
||||
if ($serviceFactory && $serviceFactory->checKExists($name)) {
|
||||
throw new Conflict('Entity name \''.$name.'\' is not allowed.');
|
||||
|
||||
@@ -99,10 +99,18 @@ class FieldManager
|
||||
if (isset($existingField)) {
|
||||
throw new Conflict('Field ['.$name.'] exists in '.$scope);
|
||||
}
|
||||
if ($this->getMetadata()->get(['entityDefs', $scope, 'links', $name])) {
|
||||
throw new Conflict('Link with name ['.$name.'] exists in '.$scope);
|
||||
}
|
||||
if (in_array($name, $this->forbiddenFieldNameList)) {
|
||||
throw new Conflict('Field ['.$name.'] is not allowed');
|
||||
}
|
||||
|
||||
$firstLatter = $name[0];
|
||||
if (is_numeric($firstLatter)) {
|
||||
throw new Conflict('Field name should begin with a letter');
|
||||
}
|
||||
|
||||
return $this->update($scope, $name, $fieldDefs, true);
|
||||
}
|
||||
|
||||
@@ -127,7 +135,7 @@ class FieldManager
|
||||
|
||||
$type = isset($fieldDefs['type']) ? $fieldDefs['type'] : $type = $this->getMetadata()->get(['entityDefs', $scope, 'fields', $name, 'type']);
|
||||
|
||||
$this->processHook('beforeSave', $type, $scope, $name, $fieldDefs);
|
||||
$this->processHook('beforeSave', $type, $scope, $name, $fieldDefs, array('isNew' => $isNew));
|
||||
|
||||
if ($this->getMetadata()->get(['fields', $type, 'translatedOptions'])) {
|
||||
if (isset($fieldDefs['translatedOptions'])) {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils\FieldManager\Hooks;
|
||||
|
||||
use Espo\Core\Exceptions\Conflict;
|
||||
|
||||
class AttachmentMultipleType extends Base
|
||||
{
|
||||
public function beforeSave($scope, $name, $defs, $options)
|
||||
{
|
||||
if (!empty($options['isNew'])) {
|
||||
$fieldDefs = $this->getMetadata()->get(['entityDefs', $scope, 'fields'], array());
|
||||
foreach ($fieldDefs as $field => $defs) {
|
||||
$type = $this->getMetadata()->get(['entityDefs', $scope, 'fields', $field, 'type']);
|
||||
if ($type === 'attachmentMultiple') {
|
||||
throw new Conflict("Attachment-Multiple field already exists in '{$scope}'. There can be only one Attachment-Multiple field per entity type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
98
application/Espo/Core/Utils/FieldManagerUtil.php
Normal file
98
application/Espo/Core/Utils/FieldManagerUtil.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils;
|
||||
|
||||
class FieldManagerUtil
|
||||
{
|
||||
private $metadata;
|
||||
|
||||
public function __construct(Metadata $metadata)
|
||||
{
|
||||
$this->metadata = $metadata;
|
||||
}
|
||||
|
||||
protected function getMetadata()
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
private function getAttributeListByType($scope, $name, $type)
|
||||
{
|
||||
$fieldType = $this->getMetadata()->get('entityDefs.' . $scope . '.fields.' . $name . '.type');
|
||||
if (!$fieldType) return [];
|
||||
|
||||
$defs = $this->getMetadata()->get('fields.' . $fieldType);
|
||||
if (!$defs) return [];
|
||||
if (is_object($defs)) {
|
||||
$defs = get_object_vars($defs);
|
||||
}
|
||||
|
||||
$fieldList = [];
|
||||
|
||||
if (isset($defs[$type . 'Fields'])) {
|
||||
$list = $defs[$type . 'Fields'];
|
||||
$naming = 'suffix';
|
||||
if (isset($defs['naming'])) {
|
||||
$naming = $defs['naming'];
|
||||
}
|
||||
if ($naming == 'prefix') {
|
||||
foreach ($list as $f) {
|
||||
$fieldList[] = $f . ucfirst($name);
|
||||
}
|
||||
} else {
|
||||
foreach ($list as $f) {
|
||||
$fieldList[] = $name . ucfirst($f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($type == 'actual') {
|
||||
$fieldList[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldList;
|
||||
}
|
||||
|
||||
public function getActualAttributeList($scope, $name)
|
||||
{
|
||||
return $this->getAttributeListByType($scope, $name, 'actual');
|
||||
}
|
||||
|
||||
public function getNotActualAttributeList($scope, $name)
|
||||
{
|
||||
return $this->getAttributeListByType($scope, $name, 'notActual');
|
||||
}
|
||||
|
||||
public function getAttributeList($scope, $name)
|
||||
{
|
||||
return array_merge($this->getActualAttributeList($scope, $name), $this->getNotActualAttributeList($scope, $name));
|
||||
}
|
||||
|
||||
}
|
||||
216
application/Espo/Core/Utils/LabelManager.php
Normal file
216
application/Espo/Core/Utils/LabelManager.php
Normal file
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils;
|
||||
|
||||
use \Espo\Core\Utils\Util;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class LabelManager extends \Espo\Core\Injectable
|
||||
{
|
||||
protected $dependencyList = [
|
||||
'config',
|
||||
'fileManager',
|
||||
'metadata',
|
||||
'defaultLanguage'
|
||||
];
|
||||
|
||||
protected $ignoreList = [
|
||||
'Global.sets'
|
||||
];
|
||||
|
||||
public function getScopeList()
|
||||
{
|
||||
$scopeList = [];
|
||||
|
||||
$languageObj = $this->getDefaultLanguage();
|
||||
|
||||
$data = $languageObj->getAll();
|
||||
foreach (array_keys($data) as $scope) {
|
||||
if (!in_array($scope, $scopeList)) {
|
||||
$scopeList[] = $scope;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->getMetadata()->get('scopes') as $scope => $data) {
|
||||
if (!in_array($scope, $scopeList)) {
|
||||
$scopeList[] = $scope;
|
||||
}
|
||||
}
|
||||
|
||||
return $scopeList;
|
||||
}
|
||||
|
||||
public function getScopeData($language, $scope)
|
||||
{
|
||||
$languageObj = new Language($language, $this->getFileManager(), $this->getMetadata());
|
||||
|
||||
$data = $languageObj->get($scope);
|
||||
|
||||
if (empty($data)) {
|
||||
return (object) [];
|
||||
}
|
||||
|
||||
if ($this->getMetadata()->get(['scopes', $scope, 'entity'])) {
|
||||
|
||||
if (empty($data['fields'])) {
|
||||
$data['fields'] = array();
|
||||
}
|
||||
foreach ($this->getMetadata()->get(['entityDefs', $scope, 'fields']) as $field => $item) {
|
||||
if (!array_key_exists($field, $data['fields'])) {
|
||||
$data['fields'][$field] = $languageObj->get('Global.fields.' . $field);
|
||||
if (is_null($data['fields'][$field])) {
|
||||
$data['fields'][$field] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (empty($data['links'])) {
|
||||
$data['links'] = array();
|
||||
}
|
||||
foreach ($this->getMetadata()->get(['entityDefs', $scope, 'links']) as $link => $item) {
|
||||
if (!array_key_exists($link, $data['links'])) {
|
||||
$data['links'][$link] = $languageObj->get('Global.links.' . $link);
|
||||
if (is_null($data['links'][$link])) {
|
||||
$data['links'][$link] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($data['labels'])) {
|
||||
$data['labels'] = array();
|
||||
}
|
||||
if (!array_key_exists('Create ' . $scope, $data['labels'])) {
|
||||
$data['labels']['Create ' . $scope] = '';
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope === 'Global') {
|
||||
if (empty($data['scopeNames'])) {
|
||||
$data['scopeNames'] = array();
|
||||
}
|
||||
if (empty($data['scopeNamesPlural'])) {
|
||||
$data['scopeNamesPlural'] = array();
|
||||
}
|
||||
foreach ($this->getMetadata()->get(['scopes']) as $scopeKey => $item) {
|
||||
if (!empty($item['entity'])) {
|
||||
if (empty($data['scopeNamesPlural'][$scopeKey])) {
|
||||
$data['scopeNamesPlural'][$scopeKey] = '';
|
||||
}
|
||||
}
|
||||
if (empty($data['scopeNames'][$scopeKey])) {
|
||||
$data['scopeNames'][$scopeKey] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if (empty($value)) {
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$finalData = array();
|
||||
|
||||
foreach ($data as $category => $item) {
|
||||
if (in_array($scope . '.' . $category, $this->ignoreList)) continue;
|
||||
foreach ($item as $key => $categoryItem) {
|
||||
if (is_array($categoryItem)) {
|
||||
foreach ($categoryItem as $subKey => $subItem) {
|
||||
$finalData[$category][$category .'[.]' . $key .'[.]' . $subKey] = $subItem;
|
||||
}
|
||||
} else {
|
||||
$finalData[$category][$category .'[.]' . $key] = $categoryItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $finalData;
|
||||
}
|
||||
|
||||
public function saveLabels($language, $scope, $labels)
|
||||
{
|
||||
$languageObj = new Language($language, $this->getFileManager(), $this->getMetadata());
|
||||
$languageOriginalObj = new Language($language, $this->getFileManager(), $this->getMetadata(), false, true);
|
||||
|
||||
$returnDataHash = array();
|
||||
|
||||
foreach ($labels as $key => $value) {
|
||||
$arr = explode('[.]', $key);
|
||||
$category = $arr[0];
|
||||
$name = $arr[1];
|
||||
|
||||
$setPath = [$scope, $category, $name];
|
||||
|
||||
$setValue = null;
|
||||
|
||||
if (count($arr) == 2) {
|
||||
if ($value !== '') {
|
||||
$languageObj->set($scope, $category, $name, $value);
|
||||
$setValue = $value;
|
||||
} else {
|
||||
$setValue = $languageOriginalObj->get(implode('.', [$scope, $category, $name]));
|
||||
if (is_null($setValue) && $scope !== 'Global') {
|
||||
$setValue = $languageOriginalObj->get(implode('.', ['Global', $category, $name]));
|
||||
}
|
||||
$languageObj->delete($scope, $category, $name);
|
||||
}
|
||||
} else if (count($arr) == 3) {
|
||||
$name = $arr[1];
|
||||
$attribute = $arr[2];
|
||||
$data = $languageObj->get($scope . '.' . $category . '.' . $name);
|
||||
|
||||
$setPath[] = $attribute;
|
||||
|
||||
if (is_array($data)) {
|
||||
if ($value !== '') {
|
||||
$data[$attribute] = $value;
|
||||
$setValue = $value;
|
||||
} else {
|
||||
$dataOriginal = $languageOriginalObj->get($scope . '.' . $category . '.' . $name);
|
||||
if (is_array($dataOriginal) && isset($dataOriginal[$attribute])) {
|
||||
$data[$attribute] = $dataOriginal[$attribute];
|
||||
$setValue = $dataOriginal[$attribute];
|
||||
}
|
||||
}
|
||||
$languageObj->set($scope, $category, $name, $data);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_null($setValue)) {
|
||||
$frontKey = implode('[.]', $setPath);
|
||||
$returnDataHash[$frontKey] = $setValue;
|
||||
}
|
||||
}
|
||||
|
||||
$languageObj->save();
|
||||
|
||||
return $returnDataHash;
|
||||
}
|
||||
}
|
||||
@@ -61,13 +61,15 @@ class Language
|
||||
|
||||
protected $useCache = false;
|
||||
|
||||
protected $noCustom = false;
|
||||
|
||||
private $paths = array(
|
||||
'corePath' => 'application/Espo/Resources/i18n',
|
||||
'modulePath' => 'application/Espo/Modules/{*}/Resources/i18n',
|
||||
'customPath' => 'custom/Espo/Custom/Resources/i18n',
|
||||
);
|
||||
|
||||
public function __construct($language = null, File\Manager $fileManager, Metadata $metadata, $useCache = false)
|
||||
public function __construct($language = null, File\Manager $fileManager, Metadata $metadata, $useCache = false, $noCustom = false)
|
||||
{
|
||||
if ($language) {
|
||||
$this->currentLanguage = $language;
|
||||
@@ -79,6 +81,7 @@ class Language
|
||||
$this->metadata = $metadata;
|
||||
|
||||
$this->useCache = $useCache;
|
||||
$this->noCustom = $noCustom;
|
||||
|
||||
$this->unifier = new \Espo\Core\Utils\File\Unifier($this->fileManager, $this->metadata);
|
||||
}
|
||||
@@ -345,7 +348,13 @@ class Language
|
||||
protected function init($reload = false)
|
||||
{
|
||||
if ($reload || !file_exists($this->getLangCacheFile()) || !$this->useCache) {
|
||||
$fullData = $this->getUnifier()->unify($this->name, $this->paths, true);
|
||||
|
||||
$paths = $this->paths;
|
||||
if ($this->noCustom) {
|
||||
unset($paths['customPath']);
|
||||
}
|
||||
|
||||
$fullData = $this->getUnifier()->unify($this->name, $paths, true);
|
||||
|
||||
$result = true;
|
||||
foreach ($fullData as $i18nName => $i18nData) {
|
||||
|
||||
@@ -111,6 +111,15 @@ class ScheduledJob
|
||||
return $this->getClassName($name);
|
||||
}
|
||||
|
||||
public function getAvailableList()
|
||||
{
|
||||
$data = $this->getAll();
|
||||
|
||||
$list = array_keys($data);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of all job names
|
||||
*
|
||||
|
||||
@@ -35,7 +35,7 @@ class ThemeManager
|
||||
|
||||
protected $metadata;
|
||||
|
||||
private $defaultName = 'Espo';
|
||||
protected $defaultName = 'Espo';
|
||||
|
||||
private $defaultStylesheet = 'Espo';
|
||||
|
||||
|
||||
@@ -63,7 +63,9 @@ return array (
|
||||
'smtpUsername' => '',
|
||||
'smtpPassword' => '',
|
||||
'languageList' => [
|
||||
'en_GB',
|
||||
'en_US',
|
||||
'es_MX',
|
||||
'cs_CZ',
|
||||
'da_DK',
|
||||
'de_DE',
|
||||
@@ -74,6 +76,7 @@ return array (
|
||||
'nb_NO',
|
||||
'nl_NL',
|
||||
'tr_TR',
|
||||
'sr_RS',
|
||||
'ro_RO',
|
||||
'ru_RU',
|
||||
'pl_PL',
|
||||
@@ -160,6 +163,9 @@ return array (
|
||||
'cleanupJobPeriod' => '1 month',
|
||||
'cleanupActionHistoryPeriod' => '15 days',
|
||||
'cleanupAuthTokenPeriod' => '1 month',
|
||||
'currencyFormat' => 1,
|
||||
'currencyDecimalPlaces' => null,
|
||||
'aclStrictMode' => false,
|
||||
'isInstalled' => false
|
||||
);
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ class Email extends \Espo\Core\ORM\Entity
|
||||
|
||||
public function getToList()
|
||||
{
|
||||
$value = $email->get('to');
|
||||
$value = $this->get('to');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
@@ -136,7 +136,7 @@ class Email extends \Espo\Core\ORM\Entity
|
||||
|
||||
public function getCcList()
|
||||
{
|
||||
$value = $email->get('cc');
|
||||
$value = $this->get('cc');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
@@ -148,7 +148,7 @@ class Email extends \Espo\Core\ORM\Entity
|
||||
|
||||
public function getBccList()
|
||||
{
|
||||
$value = $email->get('bcc');
|
||||
$value = $this->get('bcc');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
@@ -160,7 +160,7 @@ class Email extends \Espo\Core\ORM\Entity
|
||||
|
||||
public function getReplyToList()
|
||||
{
|
||||
$value = $email->get('replyTo');
|
||||
$value = $this->get('replyTo');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
|
||||
@@ -44,7 +44,9 @@ class Portal extends \Espo\Core\EntryPoints\Base
|
||||
} else if (!empty($data['id'])) {
|
||||
$id = $data['id'];
|
||||
} else {
|
||||
$id = explode('/', $_SERVER['REQUEST_URI'])[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1];
|
||||
$url = !empty($_SERVER['REDIRECT_URL']) ? $_SERVER['REDIRECT_URL'] : $_SERVER['REQUEST_URI'];
|
||||
|
||||
$id = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1];
|
||||
if (!$id) {
|
||||
$id = $this->getConfig()->get('defaultPortalId');
|
||||
}
|
||||
|
||||
@@ -61,12 +61,10 @@ class Mentions extends \Espo\Core\Hooks\Base
|
||||
}
|
||||
}
|
||||
|
||||
preg_match_all('/(@\w+)/', $post, $matches);
|
||||
preg_match_all('/(@[\w@.-]+)/', $post, $matches);
|
||||
|
||||
$mentionCount = 0;
|
||||
|
||||
|
||||
|
||||
if (is_array($matches) && !empty($matches[0]) && is_array($matches[0])) {
|
||||
$parent = null;
|
||||
if ($entity->get('parentId') && $entity->get('parentType')) {
|
||||
|
||||
@@ -113,7 +113,7 @@ class Notifications extends \Espo\Core\Hooks\Base
|
||||
if (is_array($targetUserIdList)) {
|
||||
foreach ($targetUserIdList as $userId) {
|
||||
if ($userId === $this->getUser()->id) continue;
|
||||
if (in_array($user->id, $userIdList)) continue;
|
||||
if (in_array($userId, $userIdList)) continue;
|
||||
$userIdList[] = $userId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,14 @@ class Cleanup extends \Espo\Core\Jobs\Base
|
||||
|
||||
protected $cleanupAuthTokenPeriod = '1 month';
|
||||
|
||||
protected $cleanupNotificationsPeriod = '2 months';
|
||||
|
||||
protected $cleanupRemovedNotesPeriod = '2 months';
|
||||
|
||||
protected $cleanupAttachmentsPeriod = '1 month';
|
||||
|
||||
protected $cleanupRemindersPeriod = '15 days';
|
||||
|
||||
public function run()
|
||||
{
|
||||
$this->cleanupJobs();
|
||||
@@ -97,6 +105,19 @@ class Cleanup extends \Espo\Core\Jobs\Base
|
||||
$sth->execute();
|
||||
}
|
||||
|
||||
protected function cleanupReminders()
|
||||
{
|
||||
$period = '-' . $this->getConfig()->get('cleanupRemindersPeriod', $this->cleanupRemindersPeriod);
|
||||
$datetime = new \DateTime();
|
||||
$datetime->modify($period);
|
||||
|
||||
$query = "DELETE FROM `reminder` WHERE DATE(remind_at) < '" . $datetime->format('Y-m-d') . "'";
|
||||
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
$sth = $pdo->prepare($query);
|
||||
$sth->execute();
|
||||
}
|
||||
|
||||
protected function cleanupAuthToken()
|
||||
{
|
||||
$period = '-' . $this->getConfig()->get('cleanupAuthTokenPeriod', $this->cleanupAuthTokenPeriod);
|
||||
@@ -122,7 +143,9 @@ class Cleanup extends \Espo\Core\Jobs\Base
|
||||
{
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
|
||||
$dateBefore = date('Y-m-d H:i:s', time() - 3600 * 24);
|
||||
$period = '-' . $this->getConfig()->get('cleanupAttachmentsPeriod', $this->cleanupAttachmentsPeriod);
|
||||
$datetime = new \DateTime();
|
||||
$datetime->modify($period);
|
||||
|
||||
$collection = $this->getEntityManager()->getRepository('Attachment')->where(array(
|
||||
'OR' => array(
|
||||
@@ -130,14 +153,40 @@ class Cleanup extends \Espo\Core\Jobs\Base
|
||||
'role' => ['Export File']
|
||||
)
|
||||
),
|
||||
'createdAt<' => $dateBefore
|
||||
))->limit(0, 100)->find();
|
||||
'createdAt<' => $datetime->format('Y-m-d H:i:s')
|
||||
))->limit(0, 1000)->find();
|
||||
|
||||
foreach ($collection as $e) {
|
||||
$this->getEntityManager()->removeEntity($e);
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM attachment WHERE deleted = 1 AND created_at < ".$pdo->quote($dateBefore);
|
||||
if ($this->getConfig()->get('cleanupOrphanAttachments')) {
|
||||
$collection = $this->getEntityManager()->getRepository('Attachment')->where(array(
|
||||
array(
|
||||
'role' => 'Attachment'
|
||||
),
|
||||
'OR' => array(
|
||||
array(
|
||||
'parentId' => null,
|
||||
'parentType!=' => null,
|
||||
'relatedType=' => null
|
||||
),
|
||||
array(
|
||||
'parentType' => null,
|
||||
'relatedId' => null,
|
||||
'relatedType!=' => null
|
||||
)
|
||||
),
|
||||
'createdAt<' => $datetime->format('Y-m-d H:i:s'),
|
||||
'createdAt>' => '2017-05-10 00:00:00'
|
||||
))->limit(0, 1000)->find();
|
||||
|
||||
foreach ($collection as $e) {
|
||||
$this->getEntityManager()->removeEntity($e);
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM attachment WHERE deleted = 1 AND created_at < ".$pdo->quote($datetime->format('Y-m-d H:i:s'));
|
||||
$sth = $pdo->query($sql);
|
||||
}
|
||||
|
||||
@@ -170,9 +219,11 @@ class Cleanup extends \Espo\Core\Jobs\Base
|
||||
{
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
|
||||
$dateBefore = date('Y-m-d H:i:s', time() - 3600 * 24 * 20);
|
||||
$period = '-' . $this->getConfig()->get('cleanupRemovedNotesPeriod', $this->cleanupRemovedNotesPeriod);
|
||||
$datetime = new \DateTime();
|
||||
$datetime->modify($period);
|
||||
|
||||
$sql = "SELECT * FROM `note` WHERE deleted = 1 AND created_at < ".$pdo->quote($dateBefore);
|
||||
$sql = "SELECT * FROM `note` WHERE deleted = 1 AND DATE(created_at) < ".$pdo->quote($datetime->format('Y-m-d'));
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute();
|
||||
while ($row = $sth->fetch(\PDO::FETCH_ASSOC)) {
|
||||
@@ -193,9 +244,12 @@ class Cleanup extends \Espo\Core\Jobs\Base
|
||||
{
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
|
||||
$dateBefore = date('Y-m-d H:i:s', time() - 3600 * 24 * 50);
|
||||
$period = '-' . $this->getConfig()->get('cleanupNotificationsPeriod', $this->cleanupNotificationsPeriod);
|
||||
$datetime = new \DateTime();
|
||||
$datetime->modify($period);
|
||||
|
||||
$sql = "SELECT * FROM `notification` WHERE DATE(created_at) < ".$pdo->quote($datetime->format('Y-m-d'));
|
||||
|
||||
$sql = "SELECT * FROM `notification` WHERE created_at < ".$pdo->quote($dateBefore);
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute();
|
||||
while ($row = $sth->fetch(\PDO::FETCH_ASSOC)) {
|
||||
|
||||
@@ -36,8 +36,6 @@ class Meeting extends \Espo\Core\Repositories\Event
|
||||
{
|
||||
protected function beforeSave(Entity $entity, array $options = array())
|
||||
{
|
||||
parent::beforeSave($entity, $options);
|
||||
|
||||
$parentId = $entity->get('parentId');
|
||||
$parentType = $entity->get('parentType');
|
||||
if (!empty($parentId) || !empty($parentType)) {
|
||||
@@ -61,6 +59,27 @@ class Meeting extends \Espo\Core\Repositories\Event
|
||||
}
|
||||
}
|
||||
|
||||
if (!$entity->isNew()) {
|
||||
if ($entity->isFieldChanged('dateStart') && $entity->isFieldChanged('dateStart') && !$entity->isFieldChanged('dateEnd')) {
|
||||
$dateEndPrevious = $entity->getFetched('dateEnd');
|
||||
$dateStartPrevious = $entity->getFetched('dateStart');
|
||||
if ($dateStartPrevious && $dateEndPrevious) {
|
||||
$dtStart = new \DateTime($dateStartPrevious);
|
||||
$dtEnd = new \DateTime($dateEndPrevious);
|
||||
$dt = new \DateTime($entity->get('dateStart'));
|
||||
|
||||
if ($dtStart && $dtEnd && $dt) {
|
||||
$duration = ($dtEnd->getTimestamp() - $dtStart->getTimestamp());
|
||||
$dt->modify('+' . $duration . ' seconds');
|
||||
$dateEnd = $dt->format('Y-m-d H:i:s');
|
||||
$entity->set('dateEnd', $dateEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent::beforeSave($entity, $options);
|
||||
|
||||
$assignedUserId = $entity->get('assignedUserId');
|
||||
if ($assignedUserId) {
|
||||
if ($entity->has('usersIds')) {
|
||||
@@ -98,24 +117,5 @@ class Meeting extends \Espo\Core\Repositories\Event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$entity->isNew()) {
|
||||
if ($entity->isFieldChanged('dateStart') && $entity->isFieldChanged('dateStart') && !$entity->isFieldChanged('dateEnd')) {
|
||||
$dateEndPrevious = $entity->getFetched('dateEnd');
|
||||
$dateStartPrevious = $entity->getFetched('dateStart');
|
||||
if ($dateStartPrevious && $dateEndPrevious) {
|
||||
$dtStart = new \DateTime($dateStartPrevious);
|
||||
$dtEnd = new \DateTime($dateEndPrevious);
|
||||
$dt = new \DateTime($entity->get('dateStart'));
|
||||
|
||||
if ($dtStart && $dtEnd && $dt) {
|
||||
$duration = ($dtEnd->getTimestamp() - $dtStart->getTimestamp());
|
||||
$dt->modify('+' . $duration . ' seconds');
|
||||
$dateEnd = $dt->format('Y-m-d H:i:s');
|
||||
$entity->set('dateEnd', $dateEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,14 +35,13 @@ class Opportunity extends \Espo\Core\ORM\Repositories\RDB
|
||||
{
|
||||
public function beforeSave(Entity $entity, array $options = array())
|
||||
{
|
||||
parent::beforeSave($entity, $options);
|
||||
|
||||
if ($entity->isNew()) {
|
||||
if (!$entity->has('probability') && $entity->get('stage')) {
|
||||
$probability = $this->getMetadata()->get('entityDefs.Opportunity.probabilityMap.' . $entity->get('stage'), 0);
|
||||
$entity->set('probability', $probability);
|
||||
}
|
||||
}
|
||||
|
||||
parent::beforeSave($entity, $options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ class Task extends \Espo\Core\Repositories\Event
|
||||
{
|
||||
protected $reminderDateAttribute = 'dateEnd';
|
||||
|
||||
protected $reminderSkippingStatusList = ['Completed', 'Canceled'];
|
||||
|
||||
protected function init()
|
||||
{
|
||||
parent::init();
|
||||
@@ -69,8 +71,6 @@ class Task extends \Espo\Core\Repositories\Event
|
||||
|
||||
protected function beforeSave(Entity $entity, array $options = array())
|
||||
{
|
||||
parent::beforeSave($entity, $options);
|
||||
|
||||
if ($entity->isFieldChanged('status')) {
|
||||
if ($entity->get('status') == 'Completed') {
|
||||
$entity->set('dateCompleted', date('Y-m-d H:i:s'));
|
||||
@@ -125,5 +125,7 @@ class Task extends \Espo\Core\Repositories\Event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent::beforeSave($entity, $options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"labels": {
|
||||
"Converted To": "Konvertováno do",
|
||||
"Create Lead": "Vytvořit stopu",
|
||||
"Convert": "Konvertovat"
|
||||
"Convert": "Konvertovat",
|
||||
"convert": "konvertovat"
|
||||
},
|
||||
"fields": {
|
||||
"name": "Název",
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Název",
|
||||
"emailAddress": "Email",
|
||||
"title": "Pozice",
|
||||
"website": "Web",
|
||||
"accountName": "Jméno organizace",
|
||||
"phoneNumber": "Telefon",
|
||||
"doNotCall": "Nevolat",
|
||||
"address": "Adresa",
|
||||
"description": "Popis"
|
||||
},
|
||||
"links": {
|
||||
},
|
||||
"labels": {
|
||||
"Create Target": "Vytvořit cíl",
|
||||
"Convert to Lead": "Konvertovat na stopu"
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,8 @@
|
||||
"targetLists": "Kontaktlister",
|
||||
"targetList": "Kontaktliste",
|
||||
"portalUser": "Portalbruger",
|
||||
"originalLead": "Oprindelig Lead"
|
||||
"originalLead": "Oprindelig Lead",
|
||||
"acceptanceStatus": "Acceptance Status"
|
||||
},
|
||||
"links": {
|
||||
"opportunities": "Muligheder",
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
"Create Lead": "Opret Lead",
|
||||
"Create Contact": "Opret Kontakt",
|
||||
"Create Task": "Opret Opgave",
|
||||
"Create Case": "Opret Sag"
|
||||
"Create Case": "Opret Sag",
|
||||
"Add to Contact": "Add to Contact",
|
||||
"Add to Lead": "Add to Lead"
|
||||
}
|
||||
}
|
||||
@@ -78,12 +78,12 @@
|
||||
"labels": {
|
||||
"Create InboundEmail": "Opret Indkommende Email",
|
||||
"Activities": "Aktiviteter",
|
||||
"History": "Forløb",
|
||||
"History": "Historik",
|
||||
"Attendees": "Deltagere",
|
||||
"Schedule Meeting": "Planlæg Møde",
|
||||
"Schedule Call": "Planlæg Opkald",
|
||||
"Compose Email": "Skriv Email",
|
||||
"Log Meeting": "Logge Møde",
|
||||
"Log Meeting": "Log møde",
|
||||
"Log Call": "Logge Opkald",
|
||||
"Archive Email": "Arkiver Email",
|
||||
"Create Task": "Opret Opgave",
|
||||
|
||||
@@ -38,9 +38,10 @@
|
||||
"Article": "Artikel"
|
||||
}
|
||||
},
|
||||
"tooltips": {
|
||||
},
|
||||
"presetFilters": {
|
||||
"published": "Publiseret"
|
||||
},
|
||||
"tooltips": {
|
||||
"portals": "Article will be available only in specified portals."
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
"labels": {
|
||||
"Converted To": "Konverteret Til",
|
||||
"Create Lead": "Opret Lead",
|
||||
"Convert": "Konverter"
|
||||
"Convert": "Konverter",
|
||||
"convert": "convert"
|
||||
},
|
||||
"fields": {
|
||||
"name": " Navn",
|
||||
@@ -24,7 +25,9 @@
|
||||
"campaign": "Kampagne",
|
||||
"targetLists": "Kontaktlister",
|
||||
"targetList": "Kontaktliste",
|
||||
"industry": "Industri"
|
||||
"industry": "Industri",
|
||||
"acceptanceStatus": "Acceptance Status",
|
||||
"opportunityAmountCurrency": "Opportunity Amount Currency"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Kontaktlister",
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
"amountConverted": "Beløb (konverteret)",
|
||||
"amountWeightedConverted": "Beløb Vægtet",
|
||||
"campaign": "Kampagne",
|
||||
"originalLead": "Oprindelig Lead"
|
||||
"originalLead": "Oprindelig Lead",
|
||||
"amountCurrency": "Amount Currency"
|
||||
},
|
||||
"links": {
|
||||
"contacts": "Kontakter",
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Navn",
|
||||
"emailAddress": "Email",
|
||||
"title": "Titel",
|
||||
"website": "Webside",
|
||||
"accountName": "Kontonavn",
|
||||
"phoneNumber": "Telefon",
|
||||
"doNotCall": "Ring Ikke!",
|
||||
"address": "Adresse",
|
||||
"description": "Beskrivelse"
|
||||
},
|
||||
"labels": {
|
||||
"Create Target": "Opret Mål",
|
||||
"Convert to Lead": "Konverter til Lead"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"links": {
|
||||
"targetLists": "Kontaktlister"
|
||||
},
|
||||
"fields": {
|
||||
"acceptanceStatus": "Acceptance Status"
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
"labels": {
|
||||
"Converted To": "Umgewandelt zu",
|
||||
"Create Lead": "Interessent erstellen",
|
||||
"Convert": "Umwandeln"
|
||||
"Convert": "Umwandeln",
|
||||
"convert": "umwandeln"
|
||||
},
|
||||
"fields": {
|
||||
"name": "Name",
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Name",
|
||||
"emailAddress": "E-Mail",
|
||||
"title": "Funktion",
|
||||
"website": "Webseite",
|
||||
"accountName": "Firmenname",
|
||||
"phoneNumber": "Telefon",
|
||||
"doNotCall": "Anrufe unerwünscht",
|
||||
"address": "Adresse",
|
||||
"description": "Beschreibung"
|
||||
},
|
||||
"labels": {
|
||||
"Create Target": "Zielkontakt erstellen",
|
||||
"Convert to Lead": "Zu Interessent umwandeln"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user