mirror of
https://github.com/espocrm/espocrm.git
synced 2026-03-03 16:47:00 +00:00
Compare commits
359 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
901bee6d3f | ||
|
|
72a0415207 | ||
|
|
de69652137 | ||
|
|
1cd2d6b35e | ||
|
|
9888ec8a6f | ||
|
|
ea5321577a | ||
|
|
23c772e029 | ||
|
|
e67387d9ea | ||
|
|
2156094407 | ||
|
|
03d5bf1ef2 | ||
|
|
42f57409c8 | ||
|
|
69d7ce408d | ||
|
|
15b3c0440c | ||
|
|
e1f0715c4d | ||
|
|
15aec72e97 | ||
|
|
66eade5db7 | ||
|
|
3d89e25349 | ||
|
|
7c890aa83a | ||
|
|
62a29c86ab | ||
|
|
bd57b6bb8e | ||
|
|
9ab1d16ea0 | ||
|
|
435aa28ca2 | ||
|
|
4bd375f154 | ||
|
|
d6521f9176 | ||
|
|
f8e0e4955a | ||
|
|
7957359c15 | ||
|
|
bdc3731b9a | ||
|
|
6b8af1220b | ||
|
|
58fffeaa84 | ||
|
|
5806785286 | ||
|
|
2f2d9b5f6f | ||
|
|
5af20c1ee0 | ||
|
|
7620be3b40 | ||
|
|
86f591b409 | ||
|
|
533dfe24d0 | ||
|
|
10c51dc46e | ||
|
|
a9d24a1e09 | ||
|
|
0cfe093701 | ||
|
|
11ec99fe6a | ||
|
|
b07e5a6da2 | ||
|
|
151738f896 | ||
|
|
075a370e7a | ||
|
|
e7aa147b90 | ||
|
|
2e988fab6d | ||
|
|
b38e03a53a | ||
|
|
68e01f9e6f | ||
|
|
4d32955e28 | ||
|
|
13a2aa7f03 | ||
|
|
ac91087b82 | ||
|
|
57a4a30402 | ||
|
|
dd3ee8d69a | ||
|
|
accbc9582e | ||
|
|
4a2845d7a5 | ||
|
|
9b2ae8992f | ||
|
|
1bb0038be8 | ||
|
|
6c4e73f1c4 | ||
|
|
72f5dbea87 | ||
|
|
aeb8411695 | ||
|
|
df6db9bd47 | ||
|
|
ab17044da9 | ||
|
|
7356bd98ab | ||
|
|
a631e52f63 | ||
|
|
b925100df7 | ||
|
|
eeba65440c | ||
|
|
95f72933a4 | ||
|
|
4b03e74662 | ||
|
|
b316eeb3eb | ||
|
|
53e6904ce1 | ||
|
|
e2b9647cf1 | ||
|
|
1145406531 | ||
|
|
9ce65c9a2b | ||
|
|
2ec1db8379 | ||
|
|
8074baef56 | ||
|
|
4584211c04 | ||
|
|
290099641b | ||
|
|
d0c3044e8e | ||
|
|
4e983ff440 | ||
|
|
9aba8b0d8f | ||
|
|
ee6ef6694f | ||
|
|
8330137c4e | ||
|
|
bd420ad963 | ||
|
|
e03bedf439 | ||
|
|
5cba246bb2 | ||
|
|
3490c16285 | ||
|
|
957fda9e8e | ||
|
|
b940adc341 | ||
|
|
f44a093ea9 | ||
|
|
0b6dc1ff5f | ||
|
|
907eb5feb5 | ||
|
|
17a339c318 | ||
|
|
3bea161618 | ||
|
|
b39a4a3624 | ||
|
|
2530d13d25 | ||
|
|
67e152c923 | ||
|
|
4934d4ad95 | ||
|
|
9a072949fd | ||
|
|
6e5f8676a1 | ||
|
|
5a52484295 | ||
|
|
a3338b0db7 | ||
|
|
d212d4a193 | ||
|
|
e3f9a0f607 | ||
|
|
91b7635d26 | ||
|
|
532581cb50 | ||
|
|
9b4a3a8ca9 | ||
|
|
564c397258 | ||
|
|
22e81898c0 | ||
|
|
ec863fe09a | ||
|
|
cb9a1d31d8 | ||
|
|
0e8d0495a9 | ||
|
|
fa19e5ebce | ||
|
|
b67e8960fa | ||
|
|
6efd697a1e | ||
|
|
a9379dcf0a | ||
|
|
9798f399bd | ||
|
|
a520510f9b | ||
|
|
fbfe82870f | ||
|
|
3b668f4dbd | ||
|
|
62eb54d853 | ||
|
|
81335454fd | ||
|
|
1b33221fc1 | ||
|
|
152c96838f | ||
|
|
f78af9b204 | ||
|
|
302b9e759f | ||
|
|
dab7e329df | ||
|
|
6a93fe77ca | ||
|
|
0e21a9bf91 | ||
|
|
723f504a56 | ||
|
|
121b324532 | ||
|
|
c54a4eee95 | ||
|
|
2a03797436 | ||
|
|
55dc4d1e77 | ||
|
|
cb51feef48 | ||
|
|
e75c957aad | ||
|
|
e08624fae3 | ||
|
|
e8ac486d4a | ||
|
|
1ded65b85d | ||
|
|
35b2f0e57e | ||
|
|
d6ef8e1b33 | ||
|
|
118025f646 | ||
|
|
0888752e2a | ||
|
|
df5177a565 | ||
|
|
3f03770b6e | ||
|
|
27ebac0722 | ||
|
|
e5b46bc547 | ||
|
|
468a236ce1 | ||
|
|
6fda3dd147 | ||
|
|
9f0705c82d | ||
|
|
0ab0de2371 | ||
|
|
ba7d79ef39 | ||
|
|
c0e51d85b5 | ||
|
|
80334d59ff | ||
|
|
759ad1a8d3 | ||
|
|
7c569d3880 | ||
|
|
7b21b82a2e | ||
|
|
5e86c5da8c | ||
|
|
9998f82596 | ||
|
|
9cb3f5fb3a | ||
|
|
dcce3335cd | ||
|
|
5f9b4d99f3 | ||
|
|
a6f4111383 | ||
|
|
569180ed86 | ||
|
|
f9cc21a06d | ||
|
|
e5ad31a965 | ||
|
|
5252d63260 | ||
|
|
a9fea0b9f5 | ||
|
|
cee91eb6af | ||
|
|
c61765cc31 | ||
|
|
03d3884bf4 | ||
|
|
cb01caddd3 | ||
|
|
725a2be959 | ||
|
|
45d2cec423 | ||
|
|
08b576105c | ||
|
|
6d86c65ea6 | ||
|
|
0e19fe087b | ||
|
|
2571f967b7 | ||
|
|
a93d5a0678 | ||
|
|
be1647548a | ||
|
|
91571fa47c | ||
|
|
cf3220581f | ||
|
|
44ddf9b400 | ||
|
|
99b4f7eb5c | ||
|
|
803111b12f | ||
|
|
9509d00fd4 | ||
|
|
70eb562400 | ||
|
|
2ceb686198 | ||
|
|
6f89a01c50 | ||
|
|
2d85106a1f | ||
|
|
cefe304c2f | ||
|
|
cbe4f0009b | ||
|
|
a9cad90a02 | ||
|
|
597d83c6f7 | ||
|
|
cbc3c3e921 | ||
|
|
2d1aa77ddc | ||
|
|
5357061d52 | ||
|
|
13b7db63d0 | ||
|
|
62b0020c67 | ||
|
|
4512dfd420 | ||
|
|
b1303cb50e | ||
|
|
3facbc782b | ||
|
|
cdcaf7cd24 | ||
|
|
dae249e4b2 | ||
|
|
ce782ab8bd | ||
|
|
2497ab6a5e | ||
|
|
2d00b27fb6 | ||
|
|
8d179aa719 | ||
|
|
6688e19789 | ||
|
|
1db8b94ea7 | ||
|
|
63a61349ea | ||
|
|
811066a201 | ||
|
|
0b547c26a2 | ||
|
|
15497b96d1 | ||
|
|
9c3cf0b8dd | ||
|
|
eeaff7ac9d | ||
|
|
17e48c4e9f | ||
|
|
4a878c73be | ||
|
|
f05e41afb6 | ||
|
|
ba8e63c40b | ||
|
|
5d6b9b4785 | ||
|
|
06c0a59632 | ||
|
|
f6df48278c | ||
|
|
8207684193 | ||
|
|
49ac186f80 | ||
|
|
4325e1591c | ||
|
|
16eb1e0b6d | ||
|
|
68668acf57 | ||
|
|
5e5e82d6b6 | ||
|
|
8e23ef59a3 | ||
|
|
0213064217 | ||
|
|
d360cbcb4b | ||
|
|
d1dea478f7 | ||
|
|
778e7b335e | ||
|
|
5fc502c6a2 | ||
|
|
ba5bd60931 | ||
|
|
dfb72bb3e1 | ||
|
|
c4880b77e6 | ||
|
|
8aab9d17b1 | ||
|
|
205beb068c | ||
|
|
80cf2f2e10 | ||
|
|
5982b27b90 | ||
|
|
d696ca3013 | ||
|
|
9d10218487 | ||
|
|
b41ef6094a | ||
|
|
9a9a69ace4 | ||
|
|
1000139d01 | ||
|
|
129984f4c6 | ||
|
|
d665bc54e0 | ||
|
|
69b027698d | ||
|
|
6ffff16f06 | ||
|
|
79393f16d3 | ||
|
|
5821a06f9e | ||
|
|
3eb4cf27f2 | ||
|
|
94c345c386 | ||
|
|
6fe7853eb7 | ||
|
|
c45ea08ab2 | ||
|
|
04d41e9c86 | ||
|
|
2850cffc6a | ||
|
|
0cdc15ecaf | ||
|
|
ee85ee369b | ||
|
|
738e56cc63 | ||
|
|
6b38e1561b | ||
|
|
a56d8b7d1c | ||
|
|
db6e5ee778 | ||
|
|
a0bf1af3d3 | ||
|
|
5b47178162 | ||
|
|
3f0684c1ea | ||
|
|
d2bc49755d | ||
|
|
0502c1768b | ||
|
|
cf7d21db32 | ||
|
|
977fb47efb | ||
|
|
6c7a3adcdd | ||
|
|
3b22e08840 | ||
|
|
8d79524c62 | ||
|
|
3c70f28dc0 | ||
|
|
79b37e7047 | ||
|
|
3050d8b5b5 | ||
|
|
231a40e4a8 | ||
|
|
1f1c87513b | ||
|
|
910822334e | ||
|
|
af02d721c3 | ||
|
|
faf7cb9acd | ||
|
|
73869d5674 | ||
|
|
f60732170e | ||
|
|
aecf04a4f8 | ||
|
|
7a383912c8 | ||
|
|
21c288badf | ||
|
|
65492ea1dc | ||
|
|
7fd10104cc | ||
|
|
ad85c6fa3f | ||
|
|
e32bf06e4d | ||
|
|
f363d77cb7 | ||
|
|
8986b6f426 | ||
|
|
8b35c064c8 | ||
|
|
da5ea180ab | ||
|
|
3aca557420 | ||
|
|
ea723742c7 | ||
|
|
d85675f540 | ||
|
|
9b4aeb8e4c | ||
|
|
2c539b1fe6 | ||
|
|
5f31e7e148 | ||
|
|
cc9227910f | ||
|
|
85d8dfe885 | ||
|
|
563179bec7 | ||
|
|
386ada05d6 | ||
|
|
70c2992282 | ||
|
|
36d6483a51 | ||
|
|
01039b9881 | ||
|
|
bbd1297302 | ||
|
|
88c0d8810c | ||
|
|
b365bc17db | ||
|
|
3f24e64988 | ||
|
|
7a5ce2f4ee | ||
|
|
a410fb903a | ||
|
|
ba4004d720 | ||
|
|
cdc980c2b6 | ||
|
|
3578cc9523 | ||
|
|
09ff1d1e5a | ||
|
|
8e4a6ef183 | ||
|
|
0d111a6bd8 | ||
|
|
3e503852db | ||
|
|
d3fe435115 | ||
|
|
e6a0080c0e | ||
|
|
b8ddb72d3b | ||
|
|
58953ca009 | ||
|
|
d4e98155d0 | ||
|
|
86fabe3352 | ||
|
|
c5ccf8e6da | ||
|
|
b7e0a0de23 | ||
|
|
9c2a18f0aa | ||
|
|
aa95f2cf88 | ||
|
|
8dd7f262a2 | ||
|
|
b76feba080 | ||
|
|
1b5aea85ba | ||
|
|
c89c7f5e0e | ||
|
|
bcaaf539be | ||
|
|
48f0988373 | ||
|
|
a0c0d37bfd | ||
|
|
9c696fe8d6 | ||
|
|
224e3475d8 | ||
|
|
841c5f85bd | ||
|
|
6745419a4f | ||
|
|
6bf9bb875a | ||
|
|
d6e1322775 | ||
|
|
bb0e97160c | ||
|
|
8124ceea6b | ||
|
|
b5cb0c0881 | ||
|
|
8747ccc105 | ||
|
|
8b0147484c | ||
|
|
233037a1eb | ||
|
|
11446ef857 | ||
|
|
4403131235 | ||
|
|
9dde3d0645 | ||
|
|
2fcf00ef4f | ||
|
|
e94564b5e7 | ||
|
|
c6542c0698 | ||
|
|
f74959ab00 | ||
|
|
2bb28ac270 | ||
|
|
ca64d7c8ec | ||
|
|
ce2a2a03a3 | ||
|
|
d947223b9b |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -9,7 +9,10 @@
|
||||
/client
|
||||
/test.php
|
||||
/main.html
|
||||
/frontend/client/css/bootstrap.css
|
||||
/frontend/client/css/espo.css
|
||||
/frontend/client/css/espo-vertical.css
|
||||
/frontend/client/css/sakura.css
|
||||
/frontend/client/css/sakura-vertical.css
|
||||
/tests/testData/cache/*
|
||||
composer.phar
|
||||
vendor/
|
||||
|
||||
35
Gruntfile.js
35
Gruntfile.js
@@ -59,22 +59,44 @@ module.exports = function (grunt) {
|
||||
final: ['build/tmp'],
|
||||
},
|
||||
less: {
|
||||
bootstrap: {
|
||||
espo: {
|
||||
options: {
|
||||
yuicompress: true,
|
||||
},
|
||||
files: {
|
||||
'frontend/client/css/bootstrap.css': 'frontend/less/espo/main.less',
|
||||
'frontend/client/css/espo.css': 'frontend/less/espo/main.less',
|
||||
},
|
||||
},
|
||||
sakura: {
|
||||
options: {
|
||||
yuicompress: true,
|
||||
},
|
||||
files: {
|
||||
'frontend/client/css/sakura.css': 'frontend/less/sakura/main.less',
|
||||
},
|
||||
},
|
||||
espoVertical: {
|
||||
options: {
|
||||
yuicompress: true,
|
||||
},
|
||||
files: {
|
||||
'frontend/client/css/espo-vertical.css': 'frontend/less/espo-vertical/main.less',
|
||||
},
|
||||
},
|
||||
sakuraVertical: {
|
||||
options: {
|
||||
yuicompress: true,
|
||||
},
|
||||
files: {
|
||||
'frontend/client/css/sakura-vertical.css': 'frontend/less/sakura-vertical/main.less',
|
||||
},
|
||||
}
|
||||
},
|
||||
cssmin: {
|
||||
minify: {
|
||||
files: {
|
||||
'build/tmp/client/css/espo.min.css': [
|
||||
'frontend/client/css/bootstrap.css',
|
||||
'frontend/client/css/datepicker.css',
|
||||
'frontend/client/css/jquery.timepicker.css',
|
||||
'build/tmp/client/css/espo.css': [
|
||||
'frontend/client/css/espo.css',
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -131,6 +153,7 @@ module.exports = function (grunt) {
|
||||
'rebuild.php',
|
||||
'clear_cache.php',
|
||||
'upgrade.php',
|
||||
'extension.php',
|
||||
'index.php',
|
||||
'LICENSE.txt',
|
||||
'.htaccess',
|
||||
|
||||
@@ -40,20 +40,20 @@ You need to have nodejs and Grunt CLI installed.
|
||||
|
||||
The build will be created in the `build` directory.
|
||||
|
||||
### How to make translation
|
||||
### How to make a translation
|
||||
|
||||
Build po file with command:
|
||||
`node po.js en_EN`
|
||||
(specify needed language instead of en_EN)
|
||||
|
||||
After that tranlate the generated po file.
|
||||
After that translate the generated po file.
|
||||
|
||||
Build json files from the translated po file:
|
||||
|
||||
1. Put your po file espocrm-en_EN.po to the `build` directory
|
||||
1. Put your po file espocrm-en_EN.po into `build` directory
|
||||
2. Run `node lang.js en_EN`
|
||||
|
||||
The files will be created in build directory.
|
||||
Json files will be created in build directory grouped by folders.
|
||||
|
||||
### License
|
||||
|
||||
|
||||
46
application/Espo/Acl/EmailFilter.php
Normal file
46
application/Espo/Acl/EmailFilter.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class EmailFilter extends \Espo\Core\Acl\Base
|
||||
{
|
||||
public function checkIsOwner(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->has('parentId') && $entity->has('parentType')) {
|
||||
$parentType = $entity->get('parentType');
|
||||
$parentId = $entity->get('parentId');
|
||||
if (!$parentType || !$parentId) return;
|
||||
|
||||
$parent = $this->getEntityManager()->getEntity($parentType, $parentId);
|
||||
if ($parent && $parent->has('assignedUserId') && $parent->get('assignedUserId') === $user->id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error,
|
||||
\Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Admin extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
@@ -34,17 +36,19 @@ class Admin extends \Espo\Core\Controllers\Base
|
||||
}
|
||||
}
|
||||
|
||||
public function actionRebuild($params, $data)
|
||||
public function postActionRebuild($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$result = $this->getContainer()->get('dataManager')->rebuild();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function actionClearCache($params, $data)
|
||||
public function postActionClearCache($params, $data)
|
||||
{
|
||||
$result = $this->getContainer()->get('dataManager')->clearCache();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -55,8 +59,13 @@ class Admin extends \Espo\Core\Controllers\Base
|
||||
return $scheduledJob->getAllNamesOnly();
|
||||
}
|
||||
|
||||
public function actionUploadUpgradePackage($params, $data)
|
||||
public function postActionUploadUpgradePackage($params, $data)
|
||||
{
|
||||
if ($this->getConfig()->get('restrictedMode')) {
|
||||
if (!$this->getUser()->get('isSuperAdmin')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
$upgradeManager = new \Espo\Core\UpgradeManager($this->getContainer());
|
||||
|
||||
$upgradeId = $upgradeManager->upload($data);
|
||||
@@ -68,10 +77,15 @@ class Admin extends \Espo\Core\Controllers\Base
|
||||
);
|
||||
}
|
||||
|
||||
public function actionRunUpgrade($params, $data)
|
||||
public function postActionRunUpgrade($params, $data)
|
||||
{
|
||||
$upgradeManager = new \Espo\Core\UpgradeManager($this->getContainer());
|
||||
if ($this->getConfig()->get('restrictedMode')) {
|
||||
if (!$this->getUser()->get('isSuperAdmin')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
$upgradeManager = new \Espo\Core\UpgradeManager($this->getContainer());
|
||||
$upgradeManager->install($data);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -44,7 +44,7 @@ class App extends \Espo\Core\Controllers\Base
|
||||
);
|
||||
}
|
||||
|
||||
public function actionDestroyAuthToken($params, $data)
|
||||
public function postActionDestroyAuthToken($params, $data)
|
||||
{
|
||||
$token = $data['token'];
|
||||
if (empty($token)) {
|
||||
|
||||
@@ -22,11 +22,18 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Attachment extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
public function actionUpload($params, $data)
|
||||
public function actionUpload($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
list($prefix, $contents) = explode(',', $data);
|
||||
$contents = base64_decode($contents);
|
||||
|
||||
|
||||
@@ -18,49 +18,49 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class AuthToken extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function actionUpdate($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function actionCreate($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
|
||||
public function actionListLinked($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
|
||||
public function actionMassUpdate($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
|
||||
public function actionCreateLink($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
|
||||
public function actionRemoveLink($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,25 +63,65 @@ class Email extends \Espo\Core\Controllers\Record
|
||||
return $this->getRecordService()->sendTestEmail($data);
|
||||
}
|
||||
|
||||
public function actionMarkAsRead($params, $data, $request)
|
||||
public function postActionMarkAsRead($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
if (!empty($data['ids'])) {
|
||||
$ids = $data['ids'];
|
||||
} else {
|
||||
if (!empty($data['id'])) {
|
||||
$ids = [$data['id']];
|
||||
} else {
|
||||
throw new BadRequest();
|
||||
}
|
||||
}
|
||||
if (empty($data['ids']) || !is_array($data['ids'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$ids = $data['ids'];
|
||||
|
||||
return $this->getRecordService()->markAsReadByIds($ids);
|
||||
}
|
||||
|
||||
public function actionMarkAllAsRead($params, $data, $request)
|
||||
public function postActionMarkAsNotRead($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
if (!empty($data['ids'])) {
|
||||
$ids = $data['ids'];
|
||||
} else {
|
||||
if (!empty($data['id'])) {
|
||||
$ids = [$data['id']];
|
||||
} else {
|
||||
throw new BadRequest();
|
||||
}
|
||||
}
|
||||
return $this->getRecordService()->markAsNotReadByIds($ids);
|
||||
}
|
||||
|
||||
public function postActionMarkAllAsRead($params, $data, $request)
|
||||
{
|
||||
return $this->getRecordService()->markAllAsRead();
|
||||
}
|
||||
|
||||
public function postActionMarkAsImportant($params, $data, $request)
|
||||
{
|
||||
if (!empty($data['ids'])) {
|
||||
$ids = $data['ids'];
|
||||
} else {
|
||||
if (!empty($data['id'])) {
|
||||
$ids = [$data['id']];
|
||||
} else {
|
||||
throw new BadRequest();
|
||||
}
|
||||
}
|
||||
return $this->getRecordService()->markAsImportantByIds($ids);
|
||||
}
|
||||
|
||||
public function postActionMarkAsNotImportant($params, $data, $request)
|
||||
{
|
||||
if (!empty($data['ids'])) {
|
||||
$ids = $data['ids'];
|
||||
} else {
|
||||
if (!empty($data['id'])) {
|
||||
$ids = [$data['id']];
|
||||
} else {
|
||||
throw new BadRequest();
|
||||
}
|
||||
}
|
||||
return $this->getRecordService()->markAsNotImportantByIds($ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class EmailAccount extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
29
application/Espo/Controllers/EmailFilter.php
Normal file
29
application/Espo/Controllers/EmailFilter.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
class EmailFilter extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -58,6 +58,11 @@ class Extension extends \Espo\Core\Controllers\Record
|
||||
if (!$request->isPost()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
if ($this->getConfig()->get('restrictedMode')) {
|
||||
if (!$this->getUser()->get('isSuperAdmin')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
$manager = new \Espo\Core\ExtensionManager($this->getContainer());
|
||||
|
||||
@@ -71,11 +76,14 @@ class Extension extends \Espo\Core\Controllers\Record
|
||||
if (!$request->isPost()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
if ($this->getConfig()->get('restrictedMode')) {
|
||||
if (!$this->getUser()->get('isSuperAdmin')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
$manager = new \Espo\Core\ExtensionManager($this->getContainer());
|
||||
|
||||
$manager->uninstall($data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -99,12 +107,18 @@ class Extension extends \Espo\Core\Controllers\Record
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function actionDelete($params)
|
||||
public function actionDelete($params, $data, $request)
|
||||
{
|
||||
if (!$request->isDelete()) {
|
||||
throw BadRequest();
|
||||
}
|
||||
if ($this->getConfig()->get('restrictedMode')) {
|
||||
if (!$this->getUser()->get('isSuperAdmin')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
$manager = new \Espo\Core\ExtensionManager($this->getContainer());
|
||||
|
||||
$manager->delete($params);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,13 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class ExternalAccount extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -34,7 +35,7 @@ class ExternalAccount extends \Espo\Core\Controllers\Record
|
||||
$integrations = $this->getEntityManager()->getRepository('Integration')->find();
|
||||
$arr = array();
|
||||
foreach ($integrations as $entity) {
|
||||
if ($entity->get('enabled') && $this->getMetadata()->get('integrations.' . $entity->id .'.allowUserAccounts')) {
|
||||
if ($entity->get('enabled') && $this->getMetadata()->get('integrations.' . $entity->id .'.allowUserAccounts')) {
|
||||
$arr[] = array(
|
||||
'id' => $entity->id
|
||||
);
|
||||
@@ -77,15 +78,18 @@ class ExternalAccount extends \Espo\Core\Controllers\Record
|
||||
return $entity->toArray();
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data)
|
||||
public function actionUpdate($params, $data, $request)
|
||||
{
|
||||
return $this->actionPatch($params, $data);
|
||||
return $this->actionPatch($params, $data, $request);
|
||||
}
|
||||
|
||||
public function actionPatch($params, $data)
|
||||
public function actionPatch($params, $data, $request)
|
||||
{
|
||||
list($integration, $userId) = explode('__', $params['id']);
|
||||
if (!$request->isPut() && !$request->isPost() && !$request->isPatch()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
list($integration, $userId) = explode('__', $params['id']);
|
||||
|
||||
if ($this->getUser()->id != $userId) {
|
||||
throw new Forbidden();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
@@ -29,11 +29,11 @@ class GlobalSearch extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
public function actionSearch($params, $data, $request)
|
||||
{
|
||||
$query = $params['query'];
|
||||
|
||||
$offset = $request->get('offset');
|
||||
$maxSize = $request->get('maxSize');
|
||||
|
||||
$query = $request->get('q');
|
||||
|
||||
$offset = intval($request->get('offset'));
|
||||
$maxSize = intval($request->get('maxSize'));
|
||||
|
||||
return $this->getService('GlobalSearch')->find($query, $offset, $maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +71,14 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
return $this->getContainer()->get('entityManager');
|
||||
}
|
||||
|
||||
public function actionUploadFile($params, $data)
|
||||
public function actionUploadFile($params, $data, $request)
|
||||
{
|
||||
$contents = $data;
|
||||
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$attachment = $this->getEntityManager()->getEntity('Attachment');
|
||||
$attachment->set('type', 'text/csv');
|
||||
$attachment->set('role', 'Import File');
|
||||
@@ -88,24 +92,34 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
);
|
||||
}
|
||||
|
||||
public function actionRevert($params, $data)
|
||||
public function actionRevert($params, $data, $request)
|
||||
{
|
||||
if (empty($data['id'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
return $this->getService('Import')->revert($data['id']);
|
||||
}
|
||||
|
||||
public function actionRemoveDuplicates($params, $data)
|
||||
public function actionRemoveDuplicates($params, $data, $request)
|
||||
{
|
||||
if (empty($data['id'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
return $this->getService('Import')->removeDuplicates($data['id']);
|
||||
}
|
||||
|
||||
public function actionCreate($params, $data)
|
||||
public function actionCreate($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPost() && !$request->isPut()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$importParams = array(
|
||||
'headerRow' => $data['headerRow'],
|
||||
'fieldDelimiter' => $data['fieldDelimiter'],
|
||||
@@ -119,6 +133,10 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
'action' => $data['action'],
|
||||
);
|
||||
|
||||
if (array_key_exists('updateBy', $data)) {
|
||||
$importParams['updateBy'] = $data['updateBy'];
|
||||
}
|
||||
|
||||
$attachmentId = $data['attachmentId'];
|
||||
|
||||
if (!$this->getAcl()->check($data['entityType'], 'edit')) {
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class InboundEmail extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
|
||||
@@ -18,21 +18,23 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Integration extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function actionIndex($params, $data, $request)
|
||||
{
|
||||
return false;
|
||||
@@ -40,22 +42,25 @@ class Integration extends \Espo\Core\Controllers\Record
|
||||
|
||||
public function actionRead($params, $data, $request)
|
||||
{
|
||||
$entity = $this->getEntityManager()->getEntity('Integration', $params['id']);
|
||||
$entity = $this->getEntityManager()->getEntity('Integration', $params['id']);
|
||||
return $entity->toArray();
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data)
|
||||
|
||||
public function actionUpdate($params, $data, $request)
|
||||
{
|
||||
return $this->actionPatch($params, $data);
|
||||
return $this->actionPatch($params, $data, $request);
|
||||
}
|
||||
|
||||
public function actionPatch($params, $data)
|
||||
|
||||
public function actionPatch($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPut() && !$request->isPatch()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$entity = $this->getEntityManager()->getEntity('Integration', $params['id']);
|
||||
$entity->set($data);
|
||||
$this->getEntityManager()->saveEntity($entity);
|
||||
|
||||
return $entity->toArray();
|
||||
|
||||
return $entity->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
72
application/Espo/Controllers/Job.php
Normal file
72
application/Espo/Controllers/Job.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class Job extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
public function actionCreate($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function actionPatch($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function actionListLinked($params, $data, $request)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function actionMassUpdate($params, $data, $request)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function actionCreateLink($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function actionRemoveLink($params, $data)
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ 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 Layout extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
@@ -38,12 +39,16 @@ class Layout extends \Espo\Core\Controllers\Base
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data)
|
||||
public function actionUpdate($params, $data, $request)
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
if (!$request->isPut() && !$request->isPatch()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$layoutManager = $this->getContainer()->get('layout');
|
||||
$layoutManager->set($data, $params['scope'], $params['name']);
|
||||
$result = $layoutManager->save();
|
||||
@@ -57,8 +62,20 @@ class Layout extends \Espo\Core\Controllers\Base
|
||||
return $layoutManager->get($params['scope'], $params['name']);
|
||||
}
|
||||
|
||||
public function actionPatch($params, $data)
|
||||
public function actionPatch($params, $data, $request)
|
||||
{
|
||||
return $this->actionUpdate($params, $data);
|
||||
return $this->actionUpdate($params, $data, $request);
|
||||
}
|
||||
|
||||
public function actionResetToDefault($params, $data, $request)
|
||||
{
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (empty($data['scope']) || empty($data['name'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
return $this->getContainer()->get('layout')->resetToDefault($data['scope'], $data['name']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
@@ -32,32 +32,32 @@ class Notification extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
$scope = $params['scope'];
|
||||
$id = $params['id'];
|
||||
|
||||
|
||||
$userId = $this->getUser()->id;
|
||||
|
||||
|
||||
$offset = intval($request->get('offset'));
|
||||
$maxSize = intval($request->get('maxSize'));
|
||||
|
||||
$maxSize = intval($request->get('maxSize'));
|
||||
|
||||
$params = array(
|
||||
'offset' => $offset,
|
||||
'maxSize' => $maxSize,
|
||||
);
|
||||
|
||||
$result = $this->getService('Notification')->getList($userId, $params);
|
||||
|
||||
|
||||
$result = $this->getService('Notification')->getList($userId, $params);
|
||||
|
||||
return array(
|
||||
'total' => $result['total'],
|
||||
'list' => $result['collection']->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function actionNotReadCount()
|
||||
{
|
||||
$userId = $this->getUser()->id;
|
||||
return $this->getService('Notification')->getNotReadCount($userId);
|
||||
}
|
||||
|
||||
public function actionMarkAllRead($params, $data, $request)
|
||||
|
||||
public function postActionMarkAllRead($params, $data, $request)
|
||||
{
|
||||
$userId = $this->getUser()->id;
|
||||
return $this->getService('Notification')->markAllRead($userId);
|
||||
|
||||
@@ -53,27 +53,34 @@ class Preferences extends \Espo\Core\Controllers\Base
|
||||
}
|
||||
}
|
||||
|
||||
public function actionDelete($params, $data)
|
||||
public function actionDelete($params, $data, $request)
|
||||
{
|
||||
$userId = $params['id'];
|
||||
if (empty($userId)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (!$request->isDelete()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$this->handleUserAccess($userId);
|
||||
|
||||
return $this->getEntityManager()->getRepository('Preferences')->resetToDefaults($userId);
|
||||
}
|
||||
|
||||
public function actionPatch($params, $data)
|
||||
public function actionPatch($params, $data, $request)
|
||||
{
|
||||
return $this->actionUpdate($params, $data);
|
||||
return $this->actionUpdate($params, $data, $request);
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data)
|
||||
public function actionUpdate($params, $data, $request)
|
||||
{
|
||||
$userId = $params['id'];
|
||||
$this->handleUserAccess($userId);
|
||||
|
||||
if (!$request->isPost() && !$request->isPatch() && !$request->isPut()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
if (array_key_exists('smtpPassword', $data)) {
|
||||
$data['smtpPassword'] = $this->getCrypt()->encrypt($data['smtpPassword']);
|
||||
}
|
||||
|
||||
@@ -18,12 +18,10 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
class Role extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Settings extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
@@ -46,17 +47,21 @@ class Settings extends \Espo\Core\Controllers\Base
|
||||
return $this->getConfigData();
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data)
|
||||
public function actionUpdate($params, $data, $request)
|
||||
{
|
||||
return $this->actionPatch($params, $data);
|
||||
return $this->actionPatch($params, $data, $request);
|
||||
}
|
||||
|
||||
public function actionPatch($params, $data)
|
||||
public function actionPatch($params, $data, $request)
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
if (!$request->isPut() && !$request->isPatch()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
if (isset($data['useCache']) && $data['useCache'] != $this->getConfig()->get('useCache')) {
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
class Team extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class Acl
|
||||
|
||||
public function checkScope($scope, $action = null, $isOwner = null, $inTeam = null, $entity = null)
|
||||
{
|
||||
return $this->getAclManager()->checkScope($this->getUser(), $subject, $action, $isOwner, $inTeam, $entity) ;
|
||||
return $this->getAclManager()->checkScope($this->getUser(), $scope, $action, $isOwner, $inTeam, $entity) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class Base implements Injectable
|
||||
return $this->getInjection('aclManager');
|
||||
}
|
||||
|
||||
public function checkReadOnlyTeam(User $user, $scope, $data)
|
||||
public function checkReadOnlyTeam(User $user, $data)
|
||||
{
|
||||
if (empty($data) || !is_array($data) || !isset($data['read'])) {
|
||||
return false;
|
||||
@@ -89,7 +89,7 @@ class Base implements Injectable
|
||||
return $data['read'] === 'team';
|
||||
}
|
||||
|
||||
public function checkReadOnlyOwn(User $user, $scope, $data)
|
||||
public function checkReadOnlyOwn(User $user, $data)
|
||||
{
|
||||
if (empty($data) || !is_array($data) || !isset($data['read'])) {
|
||||
return false;
|
||||
@@ -160,10 +160,11 @@ class Base implements Injectable
|
||||
if ($user->id === $entity->get('assignedUserId')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($entity->has('createdById')) {
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
} else {
|
||||
if ($entity->has('createdById')) {
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -81,7 +81,12 @@ class Table
|
||||
public function getScopeData($scope)
|
||||
{
|
||||
if (array_key_exists($scope, $this->data['table'])) {
|
||||
return $this->data['table'][$scope];
|
||||
$data = $this->data['table'][$scope];
|
||||
if (is_string($data)) {
|
||||
$data = $this->getScopeData($data);
|
||||
return $data;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ class AclManager
|
||||
return false;
|
||||
}
|
||||
$data = $this->getTable($user)->getScopeData($scope);
|
||||
return $this->getImplementation($scope)->checkReadOnlyTeam($user, $scope, $data);
|
||||
return $this->getImplementation($scope)->checkReadOnlyTeam($user, $data);
|
||||
}
|
||||
|
||||
public function checkReadOnlyOwn(User $user, $scope)
|
||||
@@ -133,7 +133,7 @@ class AclManager
|
||||
return false;
|
||||
}
|
||||
$data = $this->getTable($user)->getScopeData($scope);
|
||||
return $this->getImplementation($scope)->checkReadOnlyOwn($user, $scope, $data);
|
||||
return $this->getImplementation($scope)->checkReadOnlyOwn($user, $data);
|
||||
}
|
||||
|
||||
public function check(User $user, $subject, $action = null, $isOwner = null, $inTeam = null)
|
||||
@@ -166,7 +166,7 @@ class AclManager
|
||||
return true;
|
||||
}
|
||||
$data = $this->getTable($user)->getScopeData($entity->getEntityType());
|
||||
return $this->getImplementation($scope)->checkEntity($user, $entity, $data, $action);
|
||||
return $this->getImplementation($entity->getEntityType())->checkEntity($user, $entity, $data, $action);
|
||||
}
|
||||
|
||||
public function checkScope(User $user, $scope, $action = null, $isOwner = null, $inTeam = null, $entity = null)
|
||||
|
||||
@@ -86,10 +86,12 @@ class Application
|
||||
public function runClient()
|
||||
{
|
||||
$config = $this->getContainer()->get('config');
|
||||
$themeManager = $this->getContainer()->get('themeManager');
|
||||
|
||||
$html = file_get_contents('main.html');
|
||||
$html = str_replace('{{cacheTimestamp}}', $config->get('cacheTimestamp', 0), $html);
|
||||
$html = str_replace('{{useCache}}', $config->get('useCache') ? 'true' : 'false' , $html);
|
||||
$html = str_replace('{{stylesheet}}', $themeManager->getStylesheet(), $html);
|
||||
$html = str_replace('{{runScript}}', 'app.start();' , $html);
|
||||
echo $html;
|
||||
exit;
|
||||
|
||||
@@ -278,6 +278,14 @@ class Container
|
||||
);
|
||||
}
|
||||
|
||||
private function loadThemeManager()
|
||||
{
|
||||
return new \Espo\Core\Utils\ThemeManager(
|
||||
$this->get('config'),
|
||||
$this->get('metadata')
|
||||
);
|
||||
}
|
||||
|
||||
public function setUser($user)
|
||||
{
|
||||
$this->data['user'] = $user;
|
||||
|
||||
@@ -87,18 +87,27 @@ class ControllerManager
|
||||
$actionNameUcfirst = ucfirst($actionName);
|
||||
|
||||
$beforeMethodName = 'before' . $actionNameUcfirst;
|
||||
$actionMethodName = 'action' . $actionNameUcfirst;
|
||||
$afterMethodName = 'after' . $actionNameUcfirst;
|
||||
|
||||
$fullActionMethodName = strtolower($request->getMethod()) . ucfirst($actionMethodName);
|
||||
|
||||
if (method_exists($controller, $fullActionMethodName)) {
|
||||
$primaryActionMethodName = $fullActionMethodName;
|
||||
} else {
|
||||
$primaryActionMethodName = $actionMethodName;
|
||||
}
|
||||
|
||||
if (!method_exists($controller, $primaryActionMethodName)) {
|
||||
throw new NotFound("Action '$actionName' (".$request->getMethod().") does not exist in controller '$controllerName'");
|
||||
}
|
||||
|
||||
if (method_exists($controller, $beforeMethodName)) {
|
||||
$controller->$beforeMethodName($params, $data, $request);
|
||||
}
|
||||
$actionMethodName = 'action' . $actionNameUcfirst;
|
||||
|
||||
if (!method_exists($controller, $actionMethodName)) {
|
||||
throw new NotFound("Action '$actionMethodName' does not exist in controller '$controller'");
|
||||
}
|
||||
$result = $controller->$primaryActionMethodName($params, $data, $request);
|
||||
|
||||
$result = $controller->$actionMethodName($params, $data, $request);
|
||||
|
||||
$afterMethodName = 'after' . $actionNameUcfirst;
|
||||
if (method_exists($controller, $afterMethodName)) {
|
||||
$controller->$afterMethodName($params, $data, $request);
|
||||
}
|
||||
|
||||
@@ -124,22 +124,34 @@ class Record extends Base
|
||||
$asc = $request->get('asc') === 'true';
|
||||
$sortBy = $request->get('sortBy');
|
||||
$q = $request->get('q');
|
||||
$primaryFilter = $request->get('primaryFilter');
|
||||
$textFilter = $request->get('textFilter');
|
||||
$boolFilterList = $request->get('boolFilterList');
|
||||
|
||||
if (empty($maxSize)) {
|
||||
$maxSize = self::MAX_SIZE_LIMIT;
|
||||
}
|
||||
if (!empty($maxSize) && $maxSize > self::MAX_SIZE_LIMIT) {
|
||||
throw new Forbidden();
|
||||
throw new Forbidden("Max should should not exceed " . self::MAX_SIZE_LIMIT . ". Use pagination (offset, limit).");
|
||||
}
|
||||
|
||||
$result = $this->getRecordService()->findEntities(array(
|
||||
$params = array(
|
||||
'where' => $where,
|
||||
'offset' => $offset,
|
||||
'maxSize' => $maxSize,
|
||||
'asc' => $asc,
|
||||
'sortBy' => $sortBy,
|
||||
'q' => $q,
|
||||
));
|
||||
'textFilter' => $textFilter
|
||||
);
|
||||
if ($request->get('primaryFilter')) {
|
||||
$params['primaryFilter'] = $request->get('primaryFilter');
|
||||
}
|
||||
if ($request->get('boolFilterList')) {
|
||||
$params['boolFilterList'] = $request->get('boolFilterList');
|
||||
}
|
||||
|
||||
$result = $this->getRecordService()->findEntities($params);
|
||||
|
||||
return array(
|
||||
'total' => $result['total'],
|
||||
@@ -158,6 +170,7 @@ class Record extends Base
|
||||
$asc = $request->get('asc') === 'true';
|
||||
$sortBy = $request->get('sortBy');
|
||||
$q = $request->get('q');
|
||||
$textFilter = $request->get('textFilter');
|
||||
|
||||
if (empty($maxSize)) {
|
||||
$maxSize = self::MAX_SIZE_LIMIT;
|
||||
@@ -166,15 +179,23 @@ class Record extends Base
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
$result = $this->getRecordService()->findLinkedEntities($id, $link, array(
|
||||
$params = array(
|
||||
'where' => $where,
|
||||
'offset' => $offset,
|
||||
'maxSize' => $maxSize,
|
||||
'asc' => $asc,
|
||||
'sortBy' => $sortBy,
|
||||
'q' => $q,
|
||||
));
|
||||
'textFilter' => $textFilter
|
||||
);
|
||||
if ($request->get('primaryFilter')) {
|
||||
$params['primaryFilter'] = $request->get('primaryFilter');
|
||||
}
|
||||
if ($request->get('boolFilterList')) {
|
||||
$params['boolFilterList'] = $request->get('boolFilterList');
|
||||
}
|
||||
|
||||
$result = $this->getRecordService()->findLinkedEntities($id, $link, $params);
|
||||
|
||||
return array(
|
||||
'total' => $result['total'],
|
||||
@@ -198,7 +219,7 @@ class Record extends Base
|
||||
|
||||
public function actionExport($params, $data, $request)
|
||||
{
|
||||
if ($this->getConfig()->get('disableExport') && !$this->getUser()->isAdmin()) {
|
||||
if ($this->getConfig()->get('exportDisabled') && !$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,11 @@ abstract class Base
|
||||
return $this->getContainer()->get('fileManager');
|
||||
}
|
||||
|
||||
protected function getLanguage()
|
||||
{
|
||||
return $this->getContainer()->get('language');
|
||||
}
|
||||
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
@@ -104,6 +104,9 @@ class HookManager
|
||||
foreach ($this->data[$scope][$hookName] as $className) {
|
||||
if (empty($this->hooks[$className])) {
|
||||
$this->hooks[$className] = $this->createHookByClassName($className);
|
||||
if (empty($this->hooks[$className])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$hook = $this->hooks[$className];
|
||||
$hook->$hookName($injection, $options);
|
||||
@@ -122,7 +125,7 @@ class HookManager
|
||||
}
|
||||
return $hook;
|
||||
}
|
||||
throw new Error("Class '$className' does not exist");
|
||||
$GLOBALS['log']->error("Hook class '{$name}' does not exist.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
94
application/Espo/Core/Mail/FiltersMatcher.php
Normal file
94
application/Espo/Core/Mail/FiltersMatcher.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Mail;
|
||||
|
||||
|
||||
use \Espo\Entities\Email;
|
||||
|
||||
class FiltersMatcher
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function match(Email $email, $filterList = [])
|
||||
{
|
||||
foreach ($filterList as $filter) {
|
||||
if ($filter->get('from')) {
|
||||
if (strtolower($filter->get('from')) === strtolower($email->get('from'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($filter->get('to')) {
|
||||
if ($email->get('to')) {
|
||||
$toArr = explode(';', $email->get('to'));
|
||||
foreach ($toArr as $to) {
|
||||
if (strtolower($to) === strtolower($filter->get('to'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($filter->get('subject')) {
|
||||
if ($this->matchString($filter->get('subject'), $email->get('name'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchBody(Email $email, $filterList = [])
|
||||
{
|
||||
foreach ($filterList as $filter) {
|
||||
if ($filter->get('bodyContains')) {
|
||||
$phraseList = $filter->get('bodyContains');
|
||||
$body = $email->get('body');
|
||||
$bodyPlain = $email->get('bodyPlain');
|
||||
foreach ($phraseList as $phrase) {
|
||||
if (stripos($bodyPlain, $phrase) !== false) {
|
||||
return true;
|
||||
}
|
||||
if (stripos($body, $phrase) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function matchString($pattern, $value)
|
||||
{
|
||||
if ($pattern == $value) {
|
||||
return true;
|
||||
}
|
||||
$pattern = preg_quote($pattern, '#');
|
||||
$pattern = str_replace('\*', '.*', $pattern).'\z';
|
||||
if (preg_match('#^'.$pattern.'#', $value)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ namespace Espo\Core\Mail;
|
||||
use \Zend\Mime\Mime as Mime;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\ORM\Email;
|
||||
|
||||
class Importer
|
||||
{
|
||||
@@ -34,11 +35,14 @@ class Importer
|
||||
|
||||
private $config;
|
||||
|
||||
private $filtersMatcher;
|
||||
|
||||
public function __construct($entityManager, $fileManager, $config)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->fileManager = $fileManager;
|
||||
$this->config = $config;
|
||||
$this->filtersMatcher = new FiltersMatcher();
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
@@ -55,7 +59,12 @@ class Importer
|
||||
return $this->fileManager;
|
||||
}
|
||||
|
||||
public function importMessage($message, $userId, $teamsIds = array())
|
||||
protected function getFiltersMatcher()
|
||||
{
|
||||
return $this->filtersMatcher;
|
||||
}
|
||||
|
||||
public function importMessage($message, $userId, $teamsIds = [], $filterList = [])
|
||||
{
|
||||
try {
|
||||
$email = $this->getEntityManager()->getEntity('Email');
|
||||
@@ -82,16 +91,26 @@ class Importer
|
||||
|
||||
$toArr = $this->getAddressListFromMessage($message, 'to');
|
||||
$ccArr = $this->getAddressListFromMessage($message, 'cc');
|
||||
$replyToArr = $this->getAddressListFromMessage($message, 'replyTo');
|
||||
|
||||
$email->set('from', $fromArr[0]);
|
||||
$email->set('to', implode(';', $toArr));
|
||||
$email->set('cc', implode(';', $ccArr));
|
||||
$email->set('replyTo', implode(';', $replyToArr));
|
||||
|
||||
if ($this->getFiltersMatcher()->match($email, $filterList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (isset($message->messageId) && !empty($message->messageId)) {
|
||||
$email->set('messageId', $message->messageId);
|
||||
if (isset($message->deliveredTo)) {
|
||||
$email->set('messageIdInternal', $message->messageId . '-' . $message->deliveredTo);
|
||||
}
|
||||
if (stripos($message->messageId, '@espo-system') !== false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($duplicate = $this->findDuplicate($email)) {
|
||||
@@ -99,6 +118,7 @@ class Importer
|
||||
$usersIds = $duplicate->get('usersIds');
|
||||
$usersIds[] = $userId;
|
||||
$duplicate->set('usersIds', $usersIds);
|
||||
|
||||
$this->getEntityManager()->saveEntity($duplicate);
|
||||
|
||||
if (!empty($teamsIds)) {
|
||||
@@ -136,6 +156,10 @@ class Importer
|
||||
$this->importPartDataToEmail($email, $message, $inlineIds, 'text/plain');
|
||||
}
|
||||
|
||||
if (!$email->get('body') && $email->get('bodyPlain')) {
|
||||
$email->set('body', $email->get('bodyPlain'));
|
||||
}
|
||||
|
||||
$body = $email->get('body');
|
||||
if (!empty($body)) {
|
||||
foreach ($inlineIds as $cid => $attachmentId) {
|
||||
@@ -144,15 +168,54 @@ class Importer
|
||||
$email->set('body', $body);
|
||||
}
|
||||
|
||||
if ($this->getFiltersMatcher()->matchBody($email, $filterList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parentFound = false;
|
||||
|
||||
if (isset($message->inReplyTo) && !empty($message->inReplyTo)) {
|
||||
$arr = explode(' ', $message->inReplyTo);
|
||||
$inReplyTo = $arr[0];
|
||||
$replied = $this->getEntityManager()->getRepository('Email')->where(array(
|
||||
'messageId' => $inReplyTo
|
||||
))->findOne();
|
||||
if ($replied) {
|
||||
$email->set('repliedId', $replied->id);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($message->references) && !empty($message->references)) {
|
||||
$reference = str_replace(array('/', '@'), " ", trim($message->references, '<>'));
|
||||
$arr = explode(' ', $message->references);
|
||||
$reference = $arr[0];
|
||||
$reference = str_replace(array('/', '@'), " ", trim($reference, '<>'));
|
||||
$parentType = $parentId = null;
|
||||
$emailSent = PHP_INT_MAX;
|
||||
$n = sscanf($reference, '%s %s %d %d espo', $parentType, $parentId, $emailSent, $number);
|
||||
if ($n == 4 && $emailSent < time()) {
|
||||
if (!empty($parentType) && !empty($parentId)) {
|
||||
if ($parentType == 'Lead') {
|
||||
$parent = $this->getEntityManager()->getEntity('Lead', $parentId);
|
||||
if ($parent && $parent->get('status') == 'Converted') {
|
||||
if ($parent->get('createdAccountId')) {
|
||||
$account = $this->getEntityManager()->getEntity('Account', $parent->get('createdAccountId'));
|
||||
if ($account) {
|
||||
$parentType = 'Account';
|
||||
$parentId = $account->id;
|
||||
}
|
||||
} else {
|
||||
if ($this->getConfig()->get('b2cMode')) {
|
||||
if ($parent->get('createdContactId')) {
|
||||
$contact = $this->getEntityManager()->getEntity('Contact', $parent->get('createdContactId'));
|
||||
if ($contact) {
|
||||
$parentType = 'Contact';
|
||||
$parentId = $contact->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$email->set('parentType', $parentType);
|
||||
$email->set('parentId', $parentId);
|
||||
$parentFound = true;
|
||||
@@ -165,10 +228,15 @@ class Importer
|
||||
if ($from) {
|
||||
$parentFound = $this->findParent($email, $from);
|
||||
}
|
||||
if (!$parentFound) {
|
||||
if (!empty($toArr)) {
|
||||
$parentFound = $this->findParent($email, $toArr[0]);
|
||||
}
|
||||
}
|
||||
if (!$parentFound) {
|
||||
if (!empty($replyToArr)) {
|
||||
$parentFound = $this->findParent($email, $replyToArr[0]);
|
||||
}
|
||||
}
|
||||
if (!$parentFound) {
|
||||
if (!empty($toArr)) {
|
||||
$parentFound = $this->findParent($email, $toArr[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,12 +297,20 @@ class Importer
|
||||
}
|
||||
}
|
||||
|
||||
protected function normilizeHeader($header)
|
||||
{
|
||||
if (is_a($header, 'ArrayIterator')) {
|
||||
return $header->current();
|
||||
} else {
|
||||
return $header;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getAddressListFromMessage($message, $type)
|
||||
{
|
||||
$addressList = array();
|
||||
if (isset($message->$type)) {
|
||||
|
||||
$list = $message->getHeader($type)->getAddressList();
|
||||
$list = $this->normilizeHeader($message->getHeader($type))->getAddressList();
|
||||
foreach ($list as $address) {
|
||||
$addressList[] = $address->getEmail();
|
||||
}
|
||||
@@ -251,6 +327,15 @@ class Importer
|
||||
$type = strtok($part->contentType, ';');
|
||||
}
|
||||
|
||||
$contentDisposition = false;
|
||||
if (isset($part->ContentDisposition)) {
|
||||
if (strpos(strtolower($part->ContentDisposition), 'attachment') === 0) {
|
||||
$contentDisposition = 'attachment';
|
||||
} else if (strpos(strtolower($part->ContentDisposition), 'inline') === 0) {
|
||||
$contentDisposition = 'inline';
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($type)) {
|
||||
if (!empty($defaultContentType)) {
|
||||
$type = $defaultContentType;
|
||||
@@ -260,28 +345,26 @@ class Importer
|
||||
}
|
||||
|
||||
$encoding = null;
|
||||
|
||||
$isAttachment = true;
|
||||
|
||||
if ($type == 'text/plain' || $type == 'text/html') {
|
||||
|
||||
$isAttachment = false;
|
||||
$content = $this->getContentFromPart($part);
|
||||
if ($type == 'text/plain') {
|
||||
if ($email->get('bodyPlain')) {
|
||||
$isAttachment = true;
|
||||
} else {
|
||||
$email->set('bodyPlain', $content);
|
||||
if (!$email->get('body')) {
|
||||
$email->set('body', $content);
|
||||
if ($contentDisposition !== 'attachment') {
|
||||
$isAttachment = false;
|
||||
$content = $this->getContentFromPart($part);
|
||||
if ($type == 'text/plain') {
|
||||
$bodyPlain = '';
|
||||
if ($email->get('bodyPlain')) {
|
||||
$bodyPlain .= $email->get('bodyPlain') . "\n";
|
||||
}
|
||||
}
|
||||
} else if ($type == 'text/html') {
|
||||
if ($email->get('isHtml')) {
|
||||
$isAttachment = true;
|
||||
} else {
|
||||
$email->set('body', $content);
|
||||
$bodyPlain .= $content;
|
||||
$email->set('bodyPlain', $bodyPlain);
|
||||
} else if ($type == 'text/html') {
|
||||
$body = '';
|
||||
if ($email->get('body')) {
|
||||
$body .= $email->get('body') . "<br>";
|
||||
}
|
||||
$body .= $content;
|
||||
$email->set('isHtml', true);
|
||||
$email->set('body', $body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,13 +376,13 @@ class Importer
|
||||
$fileName = null;
|
||||
$contentId = null;
|
||||
|
||||
if (isset($part->ContentDisposition)) {
|
||||
if (strpos($part->ContentDisposition, 'attachment') === 0) {
|
||||
if ($contentDisposition) {
|
||||
if ($contentDisposition === 'attachment') {
|
||||
if (preg_match('/filename="?([^"]+)"?/i', $part->ContentDisposition, $m)) {
|
||||
$fileName = $m[1];
|
||||
$disposition = 'attachment';
|
||||
}
|
||||
} else if (strpos($part->ContentDisposition, 'inline') === 0) {
|
||||
} else if ($contentDisposition === 'inline') {
|
||||
if (isset($part->contentID)) {
|
||||
$contentId = trim($part->contentID, '<>');
|
||||
$fileName = $contentId;
|
||||
@@ -317,7 +400,7 @@ class Importer
|
||||
}
|
||||
|
||||
if (isset($part->contentTransferEncoding)) {
|
||||
$encoding = strtolower($part->getHeader('Content-Transfer-Encoding')->getTransferEncoding());
|
||||
$encoding = strtolower($this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'))->getTransferEncoding());
|
||||
}
|
||||
|
||||
$attachment = $this->getEntityManager()->getEntity('Attachment');
|
||||
@@ -365,7 +448,7 @@ class Importer
|
||||
$encoding = null;
|
||||
|
||||
if (isset($part->contentTransferEncoding)) {
|
||||
$cteHeader = $part->getHeader('Content-Transfer-Encoding');
|
||||
$cteHeader = $this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'));
|
||||
$encoding = strtolower($cteHeader->getTransferEncoding());
|
||||
}
|
||||
|
||||
@@ -376,7 +459,7 @@ class Importer
|
||||
$charset = 'UTF-8';
|
||||
|
||||
if (isset($part->contentType)) {
|
||||
$ctHeader = $part->getHeader('Content-Type');
|
||||
$ctHeader = $this->normilizeHeader($part->getHeader('Content-Type'));
|
||||
$charsetParamValue = $ctHeader->getParameter('charset');
|
||||
if (!empty($charsetParamValue)) {
|
||||
$charset = strtoupper($charsetParamValue);
|
||||
@@ -384,7 +467,7 @@ class Importer
|
||||
}
|
||||
|
||||
if (isset($part->contentTransferEncoding)) {
|
||||
$cteHeader = $part->getHeader('Content-Transfer-Encoding');
|
||||
$cteHeader = $this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'));
|
||||
if ($cteHeader->getTransferEncoding() == 'quoted-printable') {
|
||||
$content = quoted_printable_decode($content);
|
||||
}
|
||||
|
||||
69
application/Espo/Core/Mail/Mail/Header/XQueueItemId.php
Normal file
69
application/Espo/Core/Mail/Mail/Header/XQueueItemId.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework (http://framework.zend.com/)
|
||||
*
|
||||
* @link http://github.com/zendframework/zf2 for the canonical source repository
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
namespace Espo\Core\Mail\Mail\Header;
|
||||
|
||||
use \Zend\Mail\Header;
|
||||
use Zend\Mime\Mime;
|
||||
|
||||
class XQueueItemId implements Header\HeaderInterface
|
||||
{
|
||||
protected $fieldName = 'X-QueueItemId';
|
||||
|
||||
protected $id = null;
|
||||
|
||||
public static function fromString($headerLine)
|
||||
{
|
||||
list($name, $value) = Header\GenericHeader::splitHeaderLine($headerLine);
|
||||
$value = Header\HeaderWrap::mimeDecodeValue($value);
|
||||
|
||||
if (strtolower($name) !== 'x-queue-item-id') {
|
||||
throw new Header\Exception\InvalidArgumentException('Invalid header line for Message-ID string');
|
||||
}
|
||||
|
||||
$header = new static();
|
||||
$header->setId($value);
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
public function getFieldName()
|
||||
{
|
||||
return $this->fieldName;
|
||||
}
|
||||
|
||||
public function setFieldName($value)
|
||||
{
|
||||
}
|
||||
|
||||
public function setEncoding($encoding)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function getEncoding()
|
||||
{
|
||||
return 'ASCII';
|
||||
}
|
||||
|
||||
public function toString()
|
||||
{
|
||||
return $this->fieldName . ': ' . $this->getFieldValue();
|
||||
}
|
||||
|
||||
public function getFieldValue($format = Header\HeaderInterface::FORMAT_RAW)
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
@@ -131,9 +131,11 @@ class Sender
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send(Email $email, $params = array(), &$message = null)
|
||||
public function send(Email $email, $params = array(), &$message = null, $attachmetList = [])
|
||||
{
|
||||
$message = new Message();
|
||||
if (!$message) {
|
||||
$message = new Message();
|
||||
}
|
||||
$config = $this->config;
|
||||
$params = $this->params + $params;
|
||||
|
||||
@@ -206,10 +208,24 @@ class Sender
|
||||
}
|
||||
}
|
||||
|
||||
$value = $email->get('replyTo');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
foreach ($arr as $address) {
|
||||
$message->addReplyTo(trim($address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$attachmentPartList = array();
|
||||
$attachmentCollection = $email->get('attachments');
|
||||
$attachmentInlineCollection = $email->getInlineAttachments();
|
||||
|
||||
foreach ($attachmetList as $attachment) {
|
||||
$attachmentCollection[] = $attachment;
|
||||
}
|
||||
|
||||
if (!empty($attachmentCollection)) {
|
||||
foreach ($attachmentCollection as $a) {
|
||||
$fileName = 'data/upload/' . $a->id;
|
||||
@@ -311,6 +327,9 @@ class Sender
|
||||
} else {
|
||||
$messageId = '' . md5($email->get('name')) . '/' . time() . '/' . $rand . '@espo';
|
||||
}
|
||||
if ($email->get('isSystem')) {
|
||||
$messageId .= '-system';
|
||||
}
|
||||
|
||||
$messageIdHeader = new \Zend\Mail\Header\MessageId();
|
||||
$messageIdHeader->setId($messageId);
|
||||
|
||||
@@ -37,6 +37,7 @@ class Entity extends \Espo\ORM\Entity
|
||||
$collection = $this->get($field, $defs);
|
||||
$ids = array();
|
||||
$names = new \stdClass();
|
||||
$types = new \stdClass();
|
||||
if (!empty($columns)) {
|
||||
$columnsData = new \stdClass();
|
||||
}
|
||||
@@ -46,6 +47,7 @@ class Entity extends \Espo\ORM\Entity
|
||||
$id = $e->id;
|
||||
$ids[] = $id;
|
||||
$names->$id = $e->get('name');
|
||||
$types->$id = $e->get('type');
|
||||
if (!empty($columns)) {
|
||||
$columnsData->$id = new \stdClass();
|
||||
foreach ($columns as $column => $f) {
|
||||
@@ -57,6 +59,7 @@ class Entity extends \Espo\ORM\Entity
|
||||
|
||||
$this->set($field . 'Ids', $ids);
|
||||
$this->set($field . 'Names', $names);
|
||||
$this->set($field . 'Types', $types);
|
||||
if (!empty($columns)) {
|
||||
$this->set($field . 'Columns', $columnsData);
|
||||
}
|
||||
|
||||
@@ -65,6 +65,11 @@ class Base
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
protected function getAcl()
|
||||
{
|
||||
return $this->acl;
|
||||
}
|
||||
|
||||
public function setEntityType($entityType)
|
||||
{
|
||||
$this->entityType = $entityType;
|
||||
@@ -75,20 +80,20 @@ class Base
|
||||
return $this->entityType;
|
||||
}
|
||||
|
||||
protected function limit($params, &$result)
|
||||
protected function limit($offset = null, $maxSize = null, &$result)
|
||||
{
|
||||
if (isset($params['offset']) && !is_null($params['offset'])) {
|
||||
$result['offset'] = $params['offset'];
|
||||
if (!is_null($offset)) {
|
||||
$result['offset'] = $offset;
|
||||
}
|
||||
if (isset($params['maxSize']) && !is_null($params['maxSize'])) {
|
||||
$result['limit'] = $params['maxSize'];
|
||||
if (!is_null($maxSize)) {
|
||||
$result['limit'] = $maxSize;
|
||||
}
|
||||
}
|
||||
|
||||
protected function order($params, &$result)
|
||||
protected function order($sortBy, $asc, &$result)
|
||||
{
|
||||
if (!empty($params['sortBy'])) {
|
||||
$result['orderBy'] = $params['sortBy'];
|
||||
if (!empty($sortBy)) {
|
||||
$result['orderBy'] = $sortBy;
|
||||
$type = $this->metadata->get("entityDefs.{$this->entityType}.fields." . $result['orderBy'] . ".type");
|
||||
if ($type == 'link') {
|
||||
$result['orderBy'] .= 'Name';
|
||||
@@ -96,12 +101,10 @@ class Base
|
||||
$result['orderBy'] .= 'Type';
|
||||
}
|
||||
}
|
||||
if (isset($params['asc'])) {
|
||||
if ($params['asc']) {
|
||||
$result['order'] = 'ASC';
|
||||
} else {
|
||||
$result['order'] = 'DESC';
|
||||
}
|
||||
if ($asc) {
|
||||
$result['order'] = 'ASC';
|
||||
} else {
|
||||
$result['order'] = 'DESC';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,78 +121,61 @@ class Base
|
||||
return $this->seed;
|
||||
}
|
||||
|
||||
protected function textFilter($value, &$result)
|
||||
public function applyWhere($where, &$result)
|
||||
{
|
||||
$fieldDefs = $this->getSeed()->getFields();
|
||||
$fieldList = $this->getTextFilterFields();
|
||||
$d = array();
|
||||
|
||||
foreach ($fieldList as $field) {
|
||||
if (
|
||||
strlen($item['value']) >= self::MIN_LENGTH_FOR_CONTENT_SEARCH
|
||||
&&
|
||||
!empty($fieldDefs[$field]['type']) && $fieldDefs[$field]['type'] == 'text'
|
||||
) {
|
||||
$d[$field . '*'] = '%' . $value . '%';
|
||||
} else {
|
||||
$d[$field . '*'] = $value . '%';
|
||||
}
|
||||
}
|
||||
$result['whereClause'][] = array(
|
||||
'OR' => $d
|
||||
);
|
||||
$this->prepareResult($result);
|
||||
$this->where($where, $result);
|
||||
}
|
||||
|
||||
protected function where($params, &$result)
|
||||
protected function where($where, &$result)
|
||||
{
|
||||
if (!empty($params['where']) && is_array($params['where'])) {
|
||||
$where = array();
|
||||
$this->prepareResult($result);
|
||||
|
||||
foreach ($params['where'] as $item) {
|
||||
if ($item['type'] == 'bool' && !empty($item['value']) && is_array($item['value'])) {
|
||||
foreach ($item['value'] as $filter) {
|
||||
$p = $this->getBoolFilterWhere($filter);
|
||||
if (!empty($p)) {
|
||||
$params['where'][] = $p;
|
||||
}
|
||||
$this->boolFilter($filter, $result);
|
||||
$whereClause = array();
|
||||
foreach ($where as $item) {
|
||||
if ($item['type'] == 'bool' && !empty($item['value']) && is_array($item['value'])) {
|
||||
foreach ($item['value'] as $filter) {
|
||||
$p = $this->getBoolFilterWhere($filter);
|
||||
if (!empty($p)) {
|
||||
$where[] = $p;
|
||||
}
|
||||
} else if ($item['type'] == 'textFilter' && !empty($item['value'])) {
|
||||
if (!empty($item['value'])) {
|
||||
$this->textFilter($item['value'], $result);
|
||||
}
|
||||
} else if ($item['type'] == 'primary' && !empty($item['value'])) {
|
||||
$this->primaryFilter($item['value'], $result);
|
||||
$this->applyBoolFilter($filter, $result);
|
||||
}
|
||||
} else if ($item['type'] == 'textFilter' && !empty($item['value'])) {
|
||||
if (!empty($item['value'])) {
|
||||
$this->textFilter($item['value'], $result);
|
||||
}
|
||||
} else if ($item['type'] == 'primary' && !empty($item['value'])) {
|
||||
$this->applyPrimaryFilter($item['value'], $result);
|
||||
}
|
||||
}
|
||||
|
||||
$linkedWith = array();
|
||||
$inCategory = array();
|
||||
|
||||
$ignoreList = ['linkedWith', 'inCategory', 'bool', 'primary'];
|
||||
foreach ($where as $item) {
|
||||
if (!in_array($item['type'], $ignoreList)) {
|
||||
$part = $this->getWherePart($item);
|
||||
if (!empty($part)) {
|
||||
$whereClause[] = $part;
|
||||
}
|
||||
} else {
|
||||
if ($item['type'] == 'linkedWith' && !empty($item['value'])) {
|
||||
$linkedWith[$item['field']] = $item['value'];
|
||||
} else if ($item['type'] == 'inCategory' && !empty($item['value'])) {
|
||||
$inCategory[$item['field']] = $item['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$linkedWith = array();
|
||||
$inCategory = array();
|
||||
$result['whereClause'] = array_merge($result['whereClause'], $whereClause);
|
||||
|
||||
$ignoreList = ['linkedWith', 'inCategory', 'bool', 'primary'];
|
||||
foreach ($params['where'] as $item) {
|
||||
if (!in_array($item['type'], $ignoreList)) {
|
||||
$part = $this->getWherePart($item);
|
||||
if (!empty($part)) {
|
||||
$where[] = $part;
|
||||
}
|
||||
} else {
|
||||
if ($item['type'] == 'linkedWith' && !empty($item['value'])) {
|
||||
$linkedWith[$item['field']] = $item['value'];
|
||||
} else if ($item['type'] == 'inCategory' && !empty($item['value'])) {
|
||||
$inCategory[$item['field']] = $item['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result['whereClause'] = array_merge($result['whereClause'], $where);
|
||||
|
||||
if (!empty($linkedWith)) {
|
||||
$this->handleLinkedWith($linkedWith, $result);
|
||||
}
|
||||
if (!empty($inCategory)) {
|
||||
$this->handleInCategory($inCategory, $result);
|
||||
}
|
||||
if (!empty($linkedWith)) {
|
||||
$this->handleLinkedWith($linkedWith, $result);
|
||||
}
|
||||
if (!empty($inCategory)) {
|
||||
$this->handleInCategory($inCategory, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +212,7 @@ class Base
|
||||
$result['whereClause'][] = $part;
|
||||
}
|
||||
$result['joins'] = array_merge($result['joins'], $joins);
|
||||
$result['joins'] = array_unique($result['joins']);
|
||||
$result['distinct'] = true;
|
||||
}
|
||||
|
||||
@@ -255,15 +242,15 @@ class Base
|
||||
|
||||
if ($defs['type'] == 'manyMany') {
|
||||
|
||||
if (!empty($defs['relationName']) && !empty($defs['midKeys'])) {
|
||||
if (!empty($defs['midKeys'])) {
|
||||
$result['distinct'] = true;
|
||||
$result['joins'][] = $link;
|
||||
$key = $defs['midKeys'][1];
|
||||
|
||||
$relationName = lcfirst($defs['relationName']);
|
||||
$middleName = $link . 'Middle';
|
||||
|
||||
$result['customJoin'] .= "
|
||||
JOIN " . $query->toDb($pathName) . " AS `{$pathName}` ON {$pathName}.descendor_id = ".$query->sanitize($relationName) . "." . $query->toDb($key) . "
|
||||
JOIN " . $query->toDb($pathName) . " AS `{$pathName}` ON {$pathName}.descendor_id = ".$query->sanitize($middleName) . "." . $query->toDb($key) . "
|
||||
";
|
||||
$part[$pathName . '.ascendorId'] = $val;
|
||||
}
|
||||
@@ -289,27 +276,38 @@ class Base
|
||||
protected function q($params, &$result)
|
||||
{
|
||||
if (!empty($params['q'])) {
|
||||
$fieldDefs = $this->getSeed()->getFields();
|
||||
$this->textFilter($params['q'], $result);
|
||||
}
|
||||
}
|
||||
|
||||
$value = $params['q'];
|
||||
public function manageAccess(&$result)
|
||||
{
|
||||
$this->prepareResult($result);
|
||||
$this->applyAccess($result);
|
||||
}
|
||||
|
||||
$fieldList = $this->getTextFilterFields();
|
||||
$d = array();
|
||||
foreach ($fieldList as $field) {
|
||||
if (
|
||||
strlen($value) >= self::MIN_LENGTH_FOR_CONTENT_SEARCH
|
||||
&&
|
||||
!empty($fieldDefs[$field]['type']) && $fieldDefs[$field]['type'] == 'text'
|
||||
) {
|
||||
$d[$field . '*'] = '%' . $value . '%';
|
||||
} else {
|
||||
$d[$field . '*'] = $value . '%';
|
||||
}
|
||||
}
|
||||
public function manageTextFilter($textFilter, &$result)
|
||||
{
|
||||
$this->prepareResult($result);
|
||||
$this->q(array('q' => $textFilter), $result);
|
||||
}
|
||||
|
||||
$result['whereClause'][] = array(
|
||||
'OR' => $d
|
||||
);
|
||||
protected function prepareResult(&$result)
|
||||
{
|
||||
if (empty($result)) {
|
||||
$result = array();
|
||||
}
|
||||
if (empty($result['joins'])) {
|
||||
$result['joins'] = [];
|
||||
}
|
||||
if (empty($result['leftJoins'])) {
|
||||
$result['leftJoins'] = [];
|
||||
}
|
||||
if (empty($result['whereClause'])) {
|
||||
$result['whereClause'] = array();
|
||||
}
|
||||
if (empty($result['customJoin'])) {
|
||||
$result['customJoin'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,20 +315,28 @@ class Base
|
||||
{
|
||||
if ($this->acl->checkReadOnlyOwn($this->entityType)) {
|
||||
$this->accessOnlyOwn($result);
|
||||
}
|
||||
if (!$this->user->isAdmin() && $this->acl->checkReadOnlyTeam($this->entityType)) {
|
||||
$this->accessOnlyTeam($result);
|
||||
} else {
|
||||
if (!$this->user->isAdmin() && $this->acl->checkReadOnlyTeam($this->entityType)) {
|
||||
$this->accessOnlyTeam($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function accessOnlyOwn(&$result)
|
||||
{
|
||||
if (!$this->getSeed()->hasField('assignedUserId')) {
|
||||
if ($this->getSeed()->hasField('assignedUserId')) {
|
||||
$result['whereClause'][] = array(
|
||||
'assignedUserId' => $this->getUser()->id
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->getSeed()->hasField('createdById')) {
|
||||
$result['whereClause'][] = array(
|
||||
'createdById' => $this->getUser()->id
|
||||
);
|
||||
return;
|
||||
}
|
||||
$result['whereClause'][] = array(
|
||||
'assignedUserId' => $this->getUser()->id
|
||||
);
|
||||
}
|
||||
|
||||
protected function accessOnlyTeam(&$result)
|
||||
@@ -353,22 +359,48 @@ class Base
|
||||
public function getAclParams()
|
||||
{
|
||||
$result = array();
|
||||
$this->access($result);
|
||||
$this->applyAccess($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getSelectParams(array $params, $withAcl = false)
|
||||
{
|
||||
$result = array(
|
||||
'joins' => [],
|
||||
'leftJoins' => [],
|
||||
'whereClause' => [],
|
||||
'customJoin' => ''
|
||||
);
|
||||
$result = array();
|
||||
$this->prepareResult($result);
|
||||
|
||||
if (!empty($params['sortBy'])) {
|
||||
if (!array_key_exists('asc', $params)) {
|
||||
$params['asc'] = true;
|
||||
}
|
||||
$this->order($params['sortBy'], $params['asc'], $result);
|
||||
}
|
||||
|
||||
if (!isset($params['offset'])) {
|
||||
$params['offset'] = null;
|
||||
}
|
||||
if (!isset($params['maxSize'])) {
|
||||
$params['maxSize'] = null;
|
||||
}
|
||||
$this->limit($params['offset'], $params['maxSize'], $result);
|
||||
|
||||
if (!empty($params['primaryFilter'])) {
|
||||
$this->applyPrimaryFilter($params['primaryFilter'], $result);
|
||||
}
|
||||
|
||||
if (!empty($params['boolFilterList']) && is_array($params['boolFilterList'])) {
|
||||
foreach ($params['boolFilterList'] as $filterName) {
|
||||
$this->applyBoolFilter($filterName, $result);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['where']) && is_array($params['where'])) {
|
||||
$this->where($params['where'], $result);
|
||||
}
|
||||
|
||||
if (!empty($params['textFilter'])) {
|
||||
$this->textFilter($params['textFilter'], $result);
|
||||
}
|
||||
|
||||
$this->order($params, $result);
|
||||
$this->limit($params, $result);
|
||||
$this->where($params, $result);
|
||||
$this->q($params, $result);
|
||||
|
||||
if ($withAcl) {
|
||||
@@ -439,6 +471,60 @@ class Base
|
||||
$where['type'] = 'after';
|
||||
$dt->setTimezone(new \DateTimeZone('UTC'));
|
||||
$where['value'] = $dt->format($format);
|
||||
break;
|
||||
case 'lastSevenDays':
|
||||
$where['type'] = 'between';
|
||||
|
||||
$dtFrom = clone $dt;
|
||||
|
||||
$dt->setTimezone(new \DateTimeZone('UTC'));
|
||||
$to = $dt->format($format);
|
||||
|
||||
|
||||
$dtFrom->modify('-7 day');
|
||||
$dtFrom->setTime(0, 0, 0);
|
||||
$dtFrom->setTimezone(new \DateTimeZone('UTC'));
|
||||
|
||||
$from = $dtFrom->format($format);
|
||||
|
||||
$where['value'] = [$from, $to];
|
||||
|
||||
break;
|
||||
case 'lastXDays':
|
||||
$where['type'] = 'between';
|
||||
|
||||
$dtFrom = clone $dt;
|
||||
|
||||
$dt->setTimezone(new \DateTimeZone('UTC'));
|
||||
$to = $dt->format($format);
|
||||
|
||||
$number = strval(intval($item['value']));
|
||||
$dtFrom->modify('-'.$number.' day');
|
||||
$dtFrom->setTime(0, 0, 0);
|
||||
$dtFrom->setTimezone(new \DateTimeZone('UTC'));
|
||||
|
||||
$from = $dtFrom->format($format);
|
||||
|
||||
$where['value'] = [$from, $to];
|
||||
|
||||
break;
|
||||
case 'nextXDays':
|
||||
$where['type'] = 'between';
|
||||
|
||||
$dtTo = clone $dt;
|
||||
|
||||
$dt->setTimezone(new \DateTimeZone('UTC'));
|
||||
$from = $dt->format($format);
|
||||
|
||||
$number = strval(intval($item['value']));
|
||||
$dtTo->modify('+'.$number.' day');
|
||||
$dtTo->setTime(24, 59, 59);
|
||||
$dtTo->setTimezone(new \DateTimeZone('UTC'));
|
||||
|
||||
$to = $dtTo->format($format);
|
||||
|
||||
$where['value'] = [$from, $to];
|
||||
|
||||
break;
|
||||
case 'on':
|
||||
$where['type'] = 'between';
|
||||
@@ -568,6 +654,36 @@ class Base
|
||||
case 'future':
|
||||
$part[$item['field'] . '>='] = date('Y-m-d');
|
||||
break;
|
||||
case 'lastSevenDays':
|
||||
$dt1 = new \DateTime();
|
||||
$dt2 = clone $dt1;
|
||||
$dt2->modify('-7 days');
|
||||
$part['AND'] = array(
|
||||
$item['field'] . '>=' => $dt2->format('Y-m-d'),
|
||||
$item['field'] . '<=' => $dt1->format('Y-m-d'),
|
||||
);
|
||||
break;
|
||||
case 'lastXDays':
|
||||
$dt1 = new \DateTime();
|
||||
$dt2 = clone $dt1;
|
||||
$number = strval(intval($item['value']));
|
||||
|
||||
$dt2->modify('-'.$number.' days');
|
||||
$part['AND'] = array(
|
||||
$item['field'] . '>=' => $dt2->format('Y-m-d'),
|
||||
$item['field'] . '<=' => $dt1->format('Y-m-d'),
|
||||
);
|
||||
break;
|
||||
case 'nextXDays':
|
||||
$dt1 = new \DateTime();
|
||||
$dt2 = clone $dt1;
|
||||
$number = strval(intval($item['value']));
|
||||
$dt2->modify('+'.$number.' days');
|
||||
$part['AND'] = array(
|
||||
$item['field'] . '>=' => $dt1->format('Y-m-d'),
|
||||
$item['field'] . '<=' => $dt2->format('Y-m-d'),
|
||||
);
|
||||
break;
|
||||
case 'currentMonth':
|
||||
$dt = new \DateTime();
|
||||
$part['AND'] = array(
|
||||
@@ -633,19 +749,78 @@ class Base
|
||||
return $part;
|
||||
}
|
||||
|
||||
protected function boolFilter($filterName, &$result)
|
||||
public function applyOrder($sortBy, $asc, &$result)
|
||||
{
|
||||
$this->prepareResult($result);
|
||||
$this->order($sortBy, $asc, $result);
|
||||
}
|
||||
|
||||
public function applyLimit($offset, $maxSize, &$result)
|
||||
{
|
||||
$this->prepareResult($result);
|
||||
$this->limit($offset, $maxSize, $result);
|
||||
}
|
||||
|
||||
public function applyPrimaryFilter($filterName, &$result)
|
||||
{
|
||||
$this->prepareResult($result);
|
||||
|
||||
$method = 'filter' . ucfirst($filterName);
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($result);
|
||||
}
|
||||
}
|
||||
|
||||
public function applyBoolFilter($filterName, &$result)
|
||||
{
|
||||
$this->prepareResult($result);
|
||||
|
||||
$method = 'boolFilter' . ucfirst($filterName);
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($result);
|
||||
}
|
||||
}
|
||||
|
||||
protected function primaryFilter($filterName, &$result)
|
||||
public function applyTextFilter($textFilter, &$result)
|
||||
{
|
||||
$method = 'filter' . ucfirst($filterName);
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($result);
|
||||
$this->prepareResult($result);
|
||||
$this->textFilter($textFilter, $result);
|
||||
}
|
||||
|
||||
protected function textFilter($textFilter, &$result)
|
||||
{
|
||||
$fieldDefs = $this->getSeed()->getFields();
|
||||
$fieldList = $this->getTextFilterFields();
|
||||
$d = array();
|
||||
|
||||
foreach ($fieldList as $field) {
|
||||
if (
|
||||
strlen($item['value']) >= self::MIN_LENGTH_FOR_CONTENT_SEARCH
|
||||
&&
|
||||
!empty($fieldDefs[$field]['type']) && $fieldDefs[$field]['type'] == 'text'
|
||||
) {
|
||||
$d[$field . '*'] = '%' . $textFilter . '%';
|
||||
} else {
|
||||
$d[$field . '*'] = $textFilter . '%';
|
||||
}
|
||||
}
|
||||
$result['whereClause'][] = array(
|
||||
'OR' => $d
|
||||
);
|
||||
}
|
||||
|
||||
public function applyAccess(&$result)
|
||||
{
|
||||
$this->prepareResult($result);
|
||||
$this->access($result);
|
||||
}
|
||||
|
||||
protected function boolFilters($params, &$result)
|
||||
{
|
||||
if (!empty($params['boolFilterList']) && is_array($params['boolFilterList'])) {
|
||||
foreach ($params['boolFilterList'] as $filterName) {
|
||||
$this->applyBoolFilter($filterName, $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,17 @@ class Config
|
||||
|
||||
$removeData = empty($this->removeData) ? null : $this->removeData;
|
||||
|
||||
$result = $this->getFileManager()->mergePhpContents($this->configPath, $values, $removeData);
|
||||
$data = include($this->configPath);
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
|
||||
foreach ($removeData as $key) {
|
||||
unset($data[$key]);
|
||||
}
|
||||
|
||||
$result = $this->getFileManager()->putPhpContents($this->configPath, $data);
|
||||
|
||||
if ($result) {
|
||||
$this->changedData = array();
|
||||
@@ -220,7 +230,7 @@ class Config
|
||||
$restrictItems = $this->getRestrictItems($isAdmin);
|
||||
|
||||
$values = array();
|
||||
foreach($data as $key => $item) {
|
||||
foreach ($data as $key => $item) {
|
||||
if (!in_array($key, $restrictItems)) {
|
||||
$values[$key]= $item;
|
||||
}
|
||||
|
||||
@@ -25,19 +25,19 @@ namespace Espo\Core\Utils;
|
||||
class Crypt
|
||||
{
|
||||
private $config;
|
||||
|
||||
|
||||
private $key = null;
|
||||
|
||||
|
||||
private $cryptKey = null;
|
||||
|
||||
private $iv = null;
|
||||
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->cryptKey = $config->get('cryptKey', '');
|
||||
}
|
||||
|
||||
|
||||
protected function getKey()
|
||||
{
|
||||
if (empty($this->key)) {
|
||||
@@ -53,13 +53,13 @@ class Crypt
|
||||
}
|
||||
return $this->iv;
|
||||
}
|
||||
|
||||
|
||||
public function encrypt($string)
|
||||
{
|
||||
$iv = $this->getIv();
|
||||
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->getKey(), $string, MCRYPT_MODE_CBC, $iv) . $iv);
|
||||
}
|
||||
|
||||
|
||||
public function decrypt($encryptedString)
|
||||
{
|
||||
$encryptedString = base64_decode($encryptedString);
|
||||
@@ -68,7 +68,7 @@ class Crypt
|
||||
$iv = substr($encryptedString, -16);
|
||||
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->getKey(), $string, MCRYPT_MODE_CBC, $iv));
|
||||
}
|
||||
|
||||
|
||||
public function generateKey()
|
||||
{
|
||||
return md5(uniqid());
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils\Database\Orm\Fields;
|
||||
|
||||
class AttachmentMultiple extends Base
|
||||
{
|
||||
protected function load($fieldName, $entityType)
|
||||
{
|
||||
$data = array(
|
||||
$entityType => array (
|
||||
'fields' => array(
|
||||
$fieldName.'Ids' => array(
|
||||
'type' => 'varchar',
|
||||
'notStorable' => true
|
||||
),
|
||||
$fieldName.'Names' => array(
|
||||
'type' => 'varchar',
|
||||
'notStorable' => true
|
||||
),
|
||||
)
|
||||
),
|
||||
'unset' => array(
|
||||
$entityType => array(
|
||||
'fields.'.$fieldName,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ class Attachments extends HasChildren
|
||||
$entityName => array (
|
||||
'fields' => array(
|
||||
$linkName.'Types' => array(
|
||||
'type' => 'varchar',
|
||||
'type' => 'jsonObject',
|
||||
'notStorable' => true,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -66,23 +66,31 @@ class Layout
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
protected function sanitizeInput($name)
|
||||
{
|
||||
return preg_replace("([\.]{2,})", '', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Layout context
|
||||
*
|
||||
* @param $controller
|
||||
* @param $scope
|
||||
* @param $name
|
||||
*
|
||||
* @return json
|
||||
*/
|
||||
public function get($controller, $name)
|
||||
public function get($scope, $name)
|
||||
{
|
||||
if (isset($this->changedData[$controller][$name])) {
|
||||
return Json::encode($this->changedData[$controller][$name]);
|
||||
$scope = $this->sanitizeInput($scope);
|
||||
$name = $this->sanitizeInput($name);
|
||||
|
||||
if (isset($this->changedData[$scope][$name])) {
|
||||
return Json::encode($this->changedData[$scope][$name]);
|
||||
}
|
||||
|
||||
$fileFullPath = Util::concatPath($this->getLayoutPath($controller, true), $name.'.json');
|
||||
$fileFullPath = Util::concatPath($this->getLayoutPath($scope, true), $name.'.json');
|
||||
if (!file_exists($fileFullPath)) {
|
||||
$fileFullPath = Util::concatPath($this->getLayoutPath($controller), $name.'.json');
|
||||
$fileFullPath = Util::concatPath($this->getLayoutPath($scope), $name.'.json');
|
||||
}
|
||||
|
||||
if (!file_exists($fileFullPath)) {
|
||||
@@ -101,21 +109,39 @@ class Layout
|
||||
|
||||
/**
|
||||
* Set Layout data
|
||||
* Ex. $controller = Account, $name = detail then will be created a file layoutFolder/Account/detail.json
|
||||
* Ex. $scope = Account, $name = detail then will be created a file layoutFolder/Account/detail.json
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $controller - ex. Account
|
||||
* @param string $scope - ex. Account
|
||||
* @param string $name - detail
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($data, $controller, $name)
|
||||
public function set($data, $scope, $name)
|
||||
{
|
||||
if (empty($controller) || empty($name)) {
|
||||
$scope = $this->sanitizeInput($scope);
|
||||
$name = $this->sanitizeInput($name);
|
||||
|
||||
if (empty($scope) || empty($name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->changedData[$controller][$name] = $data;
|
||||
$this->changedData[$scope][$name] = $data;
|
||||
}
|
||||
|
||||
public function resetToDefault($scope, $name)
|
||||
{
|
||||
$scope = $this->sanitizeInput($scope);
|
||||
$name = $this->sanitizeInput($name);
|
||||
|
||||
$filePath = 'custom/Espo/Custom/Resources/layouts/' . $scope . '/' . $name . '.json';
|
||||
if ($this->getFileManager()->isFile($filePath)) {
|
||||
$this->getFileManager()->removeFile($filePath);
|
||||
}
|
||||
if (!empty($this->changedData[$scope]) && !empty($this->changedData[$scope][$name])) {
|
||||
unset($this->changedData[$scope][$name]);
|
||||
}
|
||||
return $this->get($scope, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,14 +154,14 @@ class Layout
|
||||
$result = true;
|
||||
|
||||
if (!empty($this->changedData)) {
|
||||
foreach ($this->changedData as $controllerName => $rowData) {
|
||||
foreach ($this->changedData as $scope => $rowData) {
|
||||
foreach ($rowData as $layoutName => $layoutData) {
|
||||
|
||||
if (empty($controllerName) || empty($layoutName)) {
|
||||
if (empty($scope) || empty($layoutName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$layoutPath = $this->getLayoutPath($controllerName, true);
|
||||
$layoutPath = $this->getLayoutPath($scope, true);
|
||||
$data = Json::encode($layoutData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$result &= $this->getFileManager()->putContents(array($layoutPath, $layoutName.'.json'), $data);
|
||||
@@ -162,17 +188,20 @@ class Layout
|
||||
|
||||
/**
|
||||
* Merge layout data
|
||||
* Ex. $controller= Account, $name= detail then will be created a file layoutFolder/Account/detail.json
|
||||
* Ex. $scope= Account, $name= detail then will be created a file layoutFolder/Account/detail.json
|
||||
*
|
||||
* @param JSON string $data
|
||||
* @param string $controller - ex. Account
|
||||
* @param string $scope - ex. Account
|
||||
* @param string $name - detail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function merge($data, $controller, $name)
|
||||
public function merge($data, $scope, $name)
|
||||
{
|
||||
$prevData = $this->get($controller, $name);
|
||||
$scope = $this->sanitizeInput($scope);
|
||||
$name = $this->sanitizeInput($name);
|
||||
|
||||
$prevData = $this->get($scope, $name);
|
||||
|
||||
$prevDataArray = Json::getArrayData($prevData);
|
||||
$dataArray = Json::getArrayData($data);
|
||||
@@ -180,7 +209,7 @@ class Layout
|
||||
$data = Util::merge($prevDataArray, $dataArray);
|
||||
$data = Json::encode($data);
|
||||
|
||||
return $this->set($data, $controller, $name);
|
||||
return $this->set($data, $scope, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,9 +237,4 @@ class Layout
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -478,8 +478,7 @@ class Metadata
|
||||
}
|
||||
}
|
||||
|
||||
krsort($modulesToSort);
|
||||
asort($modulesToSort);
|
||||
array_multisort(array_values($modulesToSort), SORT_ASC, array_keys($modulesToSort), SORT_ASC, $modulesToSort);
|
||||
|
||||
$this->moduleList = array_keys($modulesToSort);
|
||||
}
|
||||
|
||||
52
application/Espo/Core/Utils/ThemeManager.php
Normal file
52
application/Espo/Core/Utils/ThemeManager.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils;
|
||||
|
||||
class ThemeManager
|
||||
{
|
||||
protected $config;
|
||||
|
||||
protected $metadata;
|
||||
|
||||
private $defaultName = 'Espo';
|
||||
|
||||
private $defaultStylesheet = 'Espo';
|
||||
|
||||
public function __construct(Config $config, Metadata $metadata)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->metadata = $metadata;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->config->get('theme', $this->defaultName);
|
||||
}
|
||||
|
||||
public function getStylesheet()
|
||||
{
|
||||
return $this->metadata->get('themes.' . $this->getName() . '.stylesheet', 'client/css/espo.css');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ return array (
|
||||
"tabList" => array("Account", "Contact", "Lead", "Opportunity", "Calendar", "Meeting", "Call", "Task", "Case", "Email", "Document", "Campaign"),
|
||||
"quickCreateList" => array("Account", "Contact", "Lead", "Opportunity", "Meeting", "Call", "Task", "Case"),
|
||||
'calendarDefaultEntity' => 'Meeting',
|
||||
'disableExport' => false,
|
||||
'exportDisabled' => false,
|
||||
'assignmentEmailNotifications' => false,
|
||||
'assignmentEmailNotificationsEntityList' => array('Lead', 'Opportunity', 'Task', 'Case'),
|
||||
'assignmentNotificationsEntityList' => array('Meeting', 'Call', 'Task', 'Email'),
|
||||
@@ -101,6 +101,11 @@ return array (
|
||||
'maxEmailAccountCount' => 2,
|
||||
'followCreatedEntities' => false,
|
||||
'b2cMode' => false,
|
||||
'restrictedMode' => false,
|
||||
'theme' => 'Espo',
|
||||
'massEmailMaxPerHourCount' => 100,
|
||||
'personalEmailMaxPortionSize' => 10,
|
||||
'inboundEmailMaxPortionSize' => 20,
|
||||
'isInstalled' => false,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[{
|
||||
"label":"",
|
||||
"rows": [
|
||||
[{"name":"name"}]
|
||||
[{"name":"name", "fullWidth": true}, false]
|
||||
]
|
||||
}]
|
||||
|
||||
@@ -84,7 +84,10 @@ return array (
|
||||
'permissionMap',
|
||||
'permissionRules',
|
||||
'passwordSalt',
|
||||
'cryptKey'
|
||||
'cryptKey',
|
||||
'restrictedMode',
|
||||
'userLimit',
|
||||
'stylesheet'
|
||||
),
|
||||
'adminItems' =>
|
||||
array (
|
||||
@@ -113,7 +116,10 @@ return array (
|
||||
'ldapTryUsernameSplit',
|
||||
'ldapOptReferrals',
|
||||
'ldapCreateEspoUser',
|
||||
'maxEmailAccountCount'
|
||||
'maxEmailAccountCount',
|
||||
'massEmailMaxPerHourCount',
|
||||
'personalEmailMaxPortionSize',
|
||||
'inboundEmailMaxPortionSize'
|
||||
),
|
||||
'isInstalled' => false,
|
||||
);
|
||||
|
||||
@@ -99,5 +99,53 @@ class Email extends \Espo\Core\ORM\Entity
|
||||
}
|
||||
return $attachmentList;
|
||||
}
|
||||
|
||||
public function getToList()
|
||||
{
|
||||
$value = $email->get('to');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getCcList()
|
||||
{
|
||||
$value = $email->get('cc');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getBccList()
|
||||
{
|
||||
$value = $email->get('bcc');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getReplyToList()
|
||||
{
|
||||
$value = $email->get('replyTo');
|
||||
if ($value) {
|
||||
$arr = explode(';', $value);
|
||||
if (is_array($arr)) {
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
29
application/Espo/Entities/EmailFilter.php
Normal file
29
application/Espo/Entities/EmailFilter.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Entities;
|
||||
|
||||
class EmailFilter extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\EntryPoints;
|
||||
|
||||
@@ -29,7 +29,7 @@ use \Espo\Core\Exceptions\BadRequest;
|
||||
class ChangePassword extends \Espo\Core\EntryPoints\Base
|
||||
{
|
||||
public static $authRequired = false;
|
||||
|
||||
|
||||
public function run()
|
||||
{
|
||||
$requestId = $_GET['id'];
|
||||
@@ -38,6 +38,7 @@ class ChangePassword extends \Espo\Core\EntryPoints\Base
|
||||
}
|
||||
|
||||
$config = $this->getConfig();
|
||||
$themeManager = $this->getThemeManager();
|
||||
|
||||
$p = $this->getEntityManager()->getRepository('PasswordChangeRequest')->where(array(
|
||||
'requestId' => $requestId
|
||||
@@ -56,9 +57,15 @@ class ChangePassword extends \Espo\Core\EntryPoints\Base
|
||||
$html = file_get_contents('main.html');
|
||||
$html = str_replace('{{cacheTimestamp}}', $config->get('cacheTimestamp', 0), $html);
|
||||
$html = str_replace('{{useCache}}', $config->get('useCache') ? 'true' : 'false' , $html);
|
||||
$html = str_replace('{{stylesheet}}', $themeManager->getStylesheet(), $html);
|
||||
$html = str_replace('{{runScript}}', $runScript , $html);
|
||||
echo $html;
|
||||
exit;
|
||||
}
|
||||
|
||||
protected function getThemeManager()
|
||||
{
|
||||
return $this->getContainer()->get('themeManager');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ class Download extends \Espo\Core\EntryPoints\Base
|
||||
|
||||
$fileName = "data/upload/{$attachment->id}";
|
||||
|
||||
|
||||
if (!file_exists($fileName)) {
|
||||
throw new NotFound();
|
||||
}
|
||||
@@ -78,7 +79,7 @@ class Download extends \Espo\Core\EntryPoints\Base
|
||||
if ($type) {
|
||||
header('Content-Type: ' . $type);
|
||||
}
|
||||
header('Content-Disposition: ' . $disposition . '; filename=' . $attachment->get('name'));
|
||||
header("Content-Disposition: " . $disposition . ";filename=\"" . $attachment->get('name') . "\"");
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
|
||||
@@ -29,7 +29,9 @@ class Notifications extends \Espo\Core\Hooks\Base
|
||||
{
|
||||
public static $order = 10;
|
||||
|
||||
protected $noticatorsHash = array();
|
||||
protected $notifatorsHash = array();
|
||||
|
||||
private $streamService;
|
||||
|
||||
protected function init()
|
||||
{
|
||||
@@ -44,6 +46,11 @@ class Notifications extends \Espo\Core\Hooks\Base
|
||||
return $this->getInjection('container');
|
||||
}
|
||||
|
||||
protected function getServiceFactory()
|
||||
{
|
||||
return $this->getContainer()->get('serviceFactory');
|
||||
}
|
||||
|
||||
protected function getMetadata()
|
||||
{
|
||||
return $this->getInjection('metadata');
|
||||
@@ -59,7 +66,7 @@ class Notifications extends \Espo\Core\Hooks\Base
|
||||
|
||||
protected function getNotificator($entityType)
|
||||
{
|
||||
if (empty($this->noticatorsHash[$entityType])) {
|
||||
if (empty($this->notifatorsHash[$entityType])) {
|
||||
$normalizedName = Util::normilizeClassName($entityType);
|
||||
|
||||
$className = '\\Espo\\Custom\\Notificators\\' . $normalizedName;
|
||||
@@ -81,19 +88,19 @@ class Notifications extends \Espo\Core\Hooks\Base
|
||||
$notificator->inject($name, $this->getContainer()->get($name));
|
||||
}
|
||||
|
||||
$this->noticatorsHash[$entityType] = $notificator;
|
||||
$this->notifatorsHash[$entityType] = $notificator;
|
||||
}
|
||||
return $this->noticatorsHash[$entityType];
|
||||
return $this->notifatorsHash[$entityType];
|
||||
}
|
||||
|
||||
public function afterSave(Entity $entity, array $options = array())
|
||||
{
|
||||
$entityType = $entity->getEntityType();
|
||||
|
||||
if (!empty($options['silent']) && !empty($options['noNotifications'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$entityType = $entity->getEntityType();
|
||||
|
||||
if (!$this->checkHasStream($entityType)) {
|
||||
if (in_array($entityType, $this->getConfig()->get('assignmentNotificationsEntityList', []))) {
|
||||
$notificator = $this->getNotificator($entityType);
|
||||
@@ -102,5 +109,43 @@ class Notifications extends \Espo\Core\Hooks\Base
|
||||
}
|
||||
}
|
||||
|
||||
public function beforeRemove(Entity $entity, array $options = array())
|
||||
{
|
||||
if (!empty($options['silent']) && !empty($options['noNotifications'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$entityType = $entity->getEntityType();
|
||||
if ($this->checkHasStream($entityType)) {
|
||||
$followersData = $this->getStreamService()->getEntityFollowers($entity);
|
||||
foreach ($followersData['idList'] as $userId) {
|
||||
if ($userId === $this->getUser()->id) {
|
||||
continue;
|
||||
}
|
||||
$notification = $this->getEntityManager()->getEntity('Notification');
|
||||
$notification->set(array(
|
||||
'userId' => $userId,
|
||||
'type' => 'EntityRemoved',
|
||||
'data' => array(
|
||||
'entityType' => $entity->getEntityType(),
|
||||
'entityId' => $entity->id,
|
||||
'entityName' => $entity->get('name'),
|
||||
'userId' => $this->getUser()->id,
|
||||
'userName' => $this->getUser()->get('name')
|
||||
)
|
||||
));
|
||||
$this->getEntityManager()->saveEntity($notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getStreamService()
|
||||
{
|
||||
if (empty($this->streamService)) {
|
||||
$this->streamService = $this->getServiceFactory()->create('Stream');
|
||||
}
|
||||
return $this->streamService;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ class Stream extends \Espo\Core\Hooks\Base
|
||||
|
||||
protected function getAutofollowUserIdList(Entity $entity, array $ignoreList = array())
|
||||
{
|
||||
$entityType = $entity->getEntityName();
|
||||
$entityType = $entity->getEntityType();
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
$userIdList = [];
|
||||
|
||||
@@ -160,7 +160,7 @@ class Stream extends \Espo\Core\Hooks\Base
|
||||
|
||||
public function afterSave(Entity $entity, array $options = array())
|
||||
{
|
||||
$entityName = $entity->getEntityName();
|
||||
$entityName = $entity->getEntityType();
|
||||
|
||||
if ($this->checkHasStream($entity)) {
|
||||
if ($entity->isNew()) {
|
||||
|
||||
@@ -40,7 +40,7 @@ class Cleanup extends \Espo\Core\Jobs\Base
|
||||
|
||||
protected function cleanupJobs()
|
||||
{
|
||||
$query = "DELETE FROM `job` WHERE DATE(modified_at) < '".$this->getDate()."' ";
|
||||
$query = "DELETE FROM `job` WHERE DATE(modified_at) < '".$this->getCleanupFromDate()."' AND status <> 'Pending'";
|
||||
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
$sth = $pdo->prepare($query);
|
||||
@@ -64,14 +64,14 @@ class Cleanup extends \Espo\Core\Jobs\Base
|
||||
|
||||
$delSql = "DELETE FROM `scheduled_job_log_record`
|
||||
WHERE scheduled_job_id = '".$id."'
|
||||
AND DATE(created_at) < '".$this->getDate()."'
|
||||
AND DATE(created_at) < '".$this->getCleanupFromDate()."'
|
||||
AND id NOT IN ('".implode("', '", $lastRowIds)."')
|
||||
";
|
||||
$pdo->query($delSql);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getDate($format = 'Y-m-d')
|
||||
protected function getCleanupFromDate($format = 'Y-m-d')
|
||||
{
|
||||
$datetime = new \DateTime();
|
||||
$datetime->modify($this->period);
|
||||
|
||||
59
application/Espo/Modules/Crm/Acl/CampaignLogRecord.php
Normal file
59
application/Espo/Modules/Crm/Acl/CampaignLogRecord.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Acl;
|
||||
|
||||
use \Espo\Entities\User;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class CampaignLogRecord extends \Espo\Core\Acl\Base
|
||||
{
|
||||
|
||||
public function checkIsOwner(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->has('campaignId')) {
|
||||
$campaignId = $entity->get('campaignId');
|
||||
if (!$campaignId) return;
|
||||
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
if ($campaign && $this->getAclManager()->getImplementation('Campaign')->checkIsOwner($user, $campaign)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public function checkInTeam(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->has('campaignId')) {
|
||||
$campaignId = $entity->get('campaignId');
|
||||
if (!$campaignId) return;
|
||||
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
if ($campaign && $this->getAclManager()->getImplementation('Campaign')->checkInTeam($user, $campaign)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
59
application/Espo/Modules/Crm/Acl/CampaignTrackingUrl.php
Normal file
59
application/Espo/Modules/Crm/Acl/CampaignTrackingUrl.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Acl;
|
||||
|
||||
use \Espo\Entities\User;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class CampaignTrackingUrl extends \Espo\Core\Acl\Base
|
||||
{
|
||||
|
||||
public function checkIsOwner(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->has('campaignId')) {
|
||||
$campaignId = $entity->get('campaignId');
|
||||
if (!$campaignId) return;
|
||||
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
if ($campaign && $this->getAclManager()->getImplementation('Campaign')->checkIsOwner($user, $campaign)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public function checkInTeam(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->has('campaignId')) {
|
||||
$campaignId = $entity->get('campaignId');
|
||||
if (!$campaignId) return;
|
||||
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
if ($campaign && $this->getAclManager()->getImplementation('Campaign')->checkInTeam($user, $campaign)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
59
application/Espo/Modules/Crm/Acl/MassEmail.php
Normal file
59
application/Espo/Modules/Crm/Acl/MassEmail.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Acl;
|
||||
|
||||
use \Espo\Entities\User;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class MassEmail extends \Espo\Core\Acl\Base
|
||||
{
|
||||
|
||||
public function checkIsOwner(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->has('campaignId')) {
|
||||
$campaignId = $entity->get('campaignId');
|
||||
if (!$campaignId) return;
|
||||
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
if ($campaign && $this->getAclManager()->getImplementation('Campaign')->checkIsOwner($user, $campaign)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public function checkInTeam(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->has('campaignId')) {
|
||||
$campaignId = $entity->get('campaignId');
|
||||
if (!$campaignId) return;
|
||||
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
if ($campaign && $this->getAclManager()->getImplementation('Campaign')->checkInTeam($user, $campaign)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ use \Espo\Core\Exceptions\Error,
|
||||
|
||||
class Activities extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
public static $defaultAction = 'index';
|
||||
|
||||
public function actionListCalendarEvents($params, $data, $request)
|
||||
{
|
||||
@@ -43,9 +42,32 @@ class Activities extends \Espo\Core\Controllers\Base
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
|
||||
$service = $this->getService('Activities');
|
||||
return $service->getEvents($this->getUser()->id, $from, $to);
|
||||
|
||||
$userId = $request->get('userId');
|
||||
if (!$userId) {
|
||||
$userId = $this->getUser()->id;
|
||||
}
|
||||
|
||||
return $service->getEvents($userId, $from, $to);
|
||||
}
|
||||
|
||||
public function actionListUpcoming($params, $data, $request)
|
||||
{
|
||||
$service = $this->getService('Activities');
|
||||
|
||||
$userId = $request->get('userId');
|
||||
if (!$userId) {
|
||||
$userId = $this->getUser()->id;
|
||||
}
|
||||
|
||||
$offset = intval($request->get('offset'));
|
||||
$maxSize = intval($request->get('maxSize'));
|
||||
|
||||
return $service->getUpcomingActivities($userId, array(
|
||||
'offset' => $offset,
|
||||
'maxSize' => $maxSize
|
||||
));
|
||||
}
|
||||
|
||||
public function actionPopupNotifications()
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Controllers;
|
||||
|
||||
class CampaignLogRecord extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Controllers;
|
||||
|
||||
|
||||
class CampaignTrackingUrl extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
}
|
||||
33
application/Espo/Modules/Crm/Controllers/EmailQueueItem.php
Normal file
33
application/Espo/Modules/Crm/Controllers/EmailQueueItem.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Controllers;
|
||||
|
||||
class EmailQueueItem extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Controllers;
|
||||
|
||||
@@ -27,16 +27,19 @@ use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Lead extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
public function actionConvert($params, $data)
|
||||
{
|
||||
public function actionConvert($params, $data, $request)
|
||||
{
|
||||
if (empty($data['id'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$entity = $this->getRecordService()->convert($data['id'], $data['records']);
|
||||
|
||||
|
||||
if (!empty($entity)) {
|
||||
return $entity->toArray();
|
||||
}
|
||||
throw new Error();
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
64
application/Espo/Modules/Crm/Controllers/MassEmail.php
Normal file
64
application/Espo/Modules/Crm/Controllers/MassEmail.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
|
||||
class MassEmail extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
public function postActionSendTest($params, $data)
|
||||
{
|
||||
if (empty($data['id']) || empty($data['targetList']) || !is_array($data['targetList'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$id = $data['id'];
|
||||
|
||||
$targetList = [];
|
||||
foreach ($data['targetList'] as $item) {
|
||||
if (empty($item->id) || empty($item->type)) continue;
|
||||
$targetId = $item->id;
|
||||
$targetType = $item->type;
|
||||
$target = $this->getEntityManager()->getEntity($targetType, $targetId);
|
||||
if (!$target) continue;
|
||||
if (!$this->getAcl()->check($target, 'read')) {
|
||||
continue;
|
||||
}
|
||||
$targetList[] = $target;
|
||||
}
|
||||
|
||||
$massEmail = $this->getEntityManager()->getEntity('MassEmail', $id);
|
||||
if (!$massEmail) {
|
||||
throw new NotFound();
|
||||
}
|
||||
if (!$this->getAcl()->check($massEmail, 'read')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
$this->getRecordService()->createQueue($massEmail, true, $targetList);
|
||||
$this->getRecordService()->processSending($massEmail, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -45,4 +45,18 @@ class TargetList extends \Espo\Core\Controllers\Record
|
||||
return $this->getRecordService()->unlinkAll($data['id'], $data['link']);
|
||||
}
|
||||
|
||||
public function postActionCancelOptOut($params, $data)
|
||||
{
|
||||
if (empty($data['id'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (empty($data['targetType'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (empty($data['targetId'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
return $this->getRecordService()->cancelOptOut($data['id'], $data['targetType'], $data['targetId']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Entities;
|
||||
|
||||
class CampaignTrackingUrl extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
protected function _getUrlToUse()
|
||||
{
|
||||
return '{trackingUrl:' . $this->id . '}';
|
||||
}
|
||||
|
||||
protected function _hasUrlToUse()
|
||||
{
|
||||
return !$this->isNew();
|
||||
}
|
||||
}
|
||||
28
application/Espo/Modules/Crm/Entities/EmailQueueItem.php
Normal file
28
application/Espo/Modules/Crm/Entities/EmailQueueItem.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Entities;
|
||||
|
||||
class EmailQueueItem extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
|
||||
}
|
||||
28
application/Espo/Modules/Crm/Entities/MassEmail.php
Normal file
28
application/Espo/Modules/Crm/Entities/MassEmail.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Entities;
|
||||
|
||||
class MassEmail extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.phpppph
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\EntryPoints;
|
||||
|
||||
use \Espo\Core\Utils\Util;
|
||||
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class CampaignTrackOpened extends \Espo\Core\EntryPoints\Base
|
||||
{
|
||||
public static $authRequired = false;
|
||||
|
||||
public function run()
|
||||
{
|
||||
if (empty($_GET['id'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$queueItemId = $_GET['id'];
|
||||
|
||||
$queueItem = $this->getEntityManager()->getEntity('EmailQueueItem', $queueItemId);
|
||||
|
||||
if (!$queueItem) {
|
||||
throw new NotFound();
|
||||
}
|
||||
|
||||
$target = null;
|
||||
$campaign = null;
|
||||
|
||||
$targetType = $queueItem->get('targetType');
|
||||
$targetId = $queueItem->get('targetId');
|
||||
|
||||
if ($targetType && $targetId) {
|
||||
$target = $this->getEntityManager()->getEntity($targetType, $targetId);
|
||||
}
|
||||
|
||||
$massEmailId = $queueItem->get('massEmailId');
|
||||
if (!$massEmailId) return;
|
||||
$massEmail = $this->getEntityManager()->getEntity('MassEmail', $massEmailId);
|
||||
if (!$massEmail) return;
|
||||
|
||||
$campaignId = $massEmail->get('campaignId');
|
||||
if (!$campaignId) return;
|
||||
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
if (!$campaign) return;
|
||||
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
}
|
||||
$campaignService = $this->getServiceFactory()->create('Campaign');
|
||||
$campaignService->logOpened($campaignId, $queueItemId, $target);
|
||||
}
|
||||
}
|
||||
|
||||
76
application/Espo/Modules/Crm/EntryPoints/CampaignUrl.php
Normal file
76
application/Espo/Modules/Crm/EntryPoints/CampaignUrl.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.phpppph
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\EntryPoints;
|
||||
|
||||
use \Espo\Core\Utils\Util;
|
||||
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class CampaignUrl extends \Espo\Core\EntryPoints\Base
|
||||
{
|
||||
public static $authRequired = false;
|
||||
|
||||
public function run()
|
||||
{
|
||||
if (empty($_GET['id']) || empty($_GET['queueItemId'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$queueItemId = $_GET['queueItemId'];
|
||||
$trackingUrlId = $_GET['id'];
|
||||
|
||||
$queueItem = $this->getEntityManager()->getEntity('EmailQueueItem', $queueItemId);
|
||||
$trackingUrl = $this->getEntityManager()->getEntity('CampaignTrackingUrl', $trackingUrlId);
|
||||
|
||||
if (!$queueItem || !$trackingUrl) {
|
||||
throw new NotFound();
|
||||
}
|
||||
|
||||
$target = null;
|
||||
$campaign = null;
|
||||
|
||||
$targetType = $queueItem->get('targetType');
|
||||
$targetId = $queueItem->get('targetId');
|
||||
|
||||
if ($targetType && $targetId) {
|
||||
$target = $this->getEntityManager()->getEntity($targetType, $targetId);
|
||||
}
|
||||
|
||||
$campaignId = $trackingUrl->get('campaignId');
|
||||
if ($campaignId) {
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
}
|
||||
|
||||
if ($campaign && $target) {
|
||||
$campaignService = $this->getServiceFactory()->create('Campaign');
|
||||
$campaignService->logClicked($campaignId, $queueItemId, $target, $trackingUrl);
|
||||
}
|
||||
|
||||
ob_clean();
|
||||
header('Location: ' . $trackingUrl->get('url') . '');
|
||||
die;
|
||||
}
|
||||
}
|
||||
|
||||
101
application/Espo/Modules/Crm/EntryPoints/Unsubscribe.php
Normal file
101
application/Espo/Modules/Crm/EntryPoints/Unsubscribe.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.phpppph
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\EntryPoints;
|
||||
|
||||
use \Espo\Core\Utils\Util;
|
||||
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class Unsubscribe extends \Espo\Core\EntryPoints\Base
|
||||
{
|
||||
public static $authRequired = false;
|
||||
|
||||
public function run()
|
||||
{
|
||||
if (empty($_GET['id'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$queueItemId = $_GET['id'];
|
||||
|
||||
$queueItem = $this->getEntityManager()->getEntity('EmailQueueItem', $queueItemId);
|
||||
|
||||
if (!$queueItem) {
|
||||
throw new NotFound();
|
||||
}
|
||||
|
||||
$campaign = null;
|
||||
$target = null;
|
||||
|
||||
$massEmailId = $queueItem->get('massEmailId');
|
||||
if ($massEmailId) {
|
||||
$massEmail = $this->getEntityManager()->getEntity('MassEmail', $massEmailId);
|
||||
if ($massEmail) {
|
||||
$campaignId = $massEmail->get('campaignId');
|
||||
if ($campaignId) {
|
||||
$campaign = $this->getEntityManager()->getEntity('Campaign', $campaignId);
|
||||
}
|
||||
|
||||
$targetType = $queueItem->get('targetType');
|
||||
$targetId = $queueItem->get('targetId');
|
||||
|
||||
if ($targetType && $targetId) {
|
||||
$target = $this->getEntityManager()->getEntity($targetType, $targetId);
|
||||
|
||||
$link = null;
|
||||
$m = array(
|
||||
'Account' => 'accounts',
|
||||
'Contact' => 'contacts',
|
||||
'Lead' => 'leads',
|
||||
'User' => 'users'
|
||||
);
|
||||
if (!empty($m[$target->getEntityType()])) {
|
||||
$link = $m[$target->getEntityType()];
|
||||
}
|
||||
if ($link) {
|
||||
if ($campaign) {
|
||||
$targetListList = $campaign->get('targetLists');
|
||||
} else {
|
||||
$targetListList = $massEmail->get('targetLists');
|
||||
}
|
||||
foreach ($targetListList as $targetList) {
|
||||
$this->getEntityManager()->getRepository('TargetList')->updateRelation($targetList, $link, $target->id, array(
|
||||
'optedOut' => true
|
||||
));
|
||||
}
|
||||
echo $this->getLanguage()->translate('unsubscribed', 'messages', 'Campaign');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($campaign && $target) {
|
||||
$campaignService = $this->getServiceFactory()->create('Campaign');
|
||||
$campaignService->logOptedOut($campaignId, $queueItemId, $target, $queueItem->get('emailAddress'));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class CheckEmailAccounts extends \Espo\Core\Jobs\Base
|
||||
try {
|
||||
$service->fetchFromMailServer($entity);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('Job CheckEmailAccounts: [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
$GLOBALS['log']->error('Job CheckEmailAccounts '.$entity->id.': [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class CheckInboundEmails extends \Espo\Core\Jobs\Base
|
||||
try {
|
||||
$service->fetchFromMailServer($entity);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('Job CheckInboundEmails: [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
$GLOBALS['log']->error('Job CheckInboundEmails '.$entity->id.': [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
59
application/Espo/Modules/Crm/Jobs/ProcessMassEmail.php
Normal file
59
application/Espo/Modules/Crm/Jobs/ProcessMassEmail.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Jobs;
|
||||
|
||||
use \Espo\Core\Exceptions;
|
||||
|
||||
class ProcessMassEmail extends \Espo\Core\Jobs\Base
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$service = $this->getServiceFactory()->create('MassEmail');
|
||||
|
||||
$massEmailList = $this->getEntityManager()->getRepository('MassEmail')->where(array(
|
||||
'status' => 'Pending',
|
||||
'startAt<=' => date('Y-m-d H:i:s')
|
||||
))->find();
|
||||
foreach ($massEmailList as $massEmail) {
|
||||
try {
|
||||
$service->createQueue($massEmail);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('Job ProcessMassEmail#createQueue '.$massEmail->id.': [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$massEmailList = $this->getEntityManager()->getRepository('MassEmail')->where(array(
|
||||
'status' => 'In Process'
|
||||
))->find();
|
||||
foreach ($massEmailList as $massEmail) {
|
||||
try {
|
||||
$service->processSending($massEmail);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('Job ProcessMassEmail#processSending '.$massEmail->id.': [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
67
application/Espo/Modules/Crm/Repositories/CaseObj.php
Normal file
67
application/Espo/Modules/Crm/Repositories/CaseObj.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 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/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Repositories;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class CaseObj extends \Espo\Core\ORM\Repositories\RDB
|
||||
{
|
||||
public function afterSave(Entity $entity, array $options)
|
||||
{
|
||||
$result = parent::afterSave($entity, $options);
|
||||
$this->handleAfterSaveContacts($entity, $options);
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function handleAfterSaveContacts(Entity $entity, array $options)
|
||||
{
|
||||
$contactIdChanged = $entity->has('contactId') && $entity->get('contactId') != $entity->getFetched('contactId');
|
||||
|
||||
if ($contactIdChanged) {
|
||||
$contactId = $entity->get('contactId');
|
||||
if (empty($contactId)) {
|
||||
$this->unrelate($entity, 'contacts', $entity->getFetched('contactId'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($contactIdChanged) {
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
|
||||
$sql = "
|
||||
SELECT id FROM case_contact
|
||||
WHERE
|
||||
contact_id = ".$pdo->quote($contactId)." AND
|
||||
case_id = ".$pdo->quote($entity->id)." AND
|
||||
deleted = 0
|
||||
";
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute();
|
||||
|
||||
if (!$sth->fetch()) {
|
||||
$this->relate($entity, 'contacts', $contactId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,17 @@ class Contact extends \Espo\Core\ORM\Repositories\RDB
|
||||
public function afterSave(Entity $entity, array $options)
|
||||
{
|
||||
$result = parent::afterSave($entity, $options);
|
||||
$this->handleAfterSaveAccounts($entity, $options);
|
||||
|
||||
if ($entity->has('targetListId')) {
|
||||
$this->relate($entity, 'targetLists', $entity->get('targetListId'));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function handleAfterSaveAccounts(Entity $entity, array $options)
|
||||
{
|
||||
$accountIdChanged = $entity->has('accountId') && $entity->get('accountId') != $entity->getFetched('accountId');
|
||||
$titleChanged = $entity->has('title') && $entity->get('title') != $entity->getFetched('title');
|
||||
|
||||
@@ -51,7 +61,7 @@ class Contact extends \Espo\Core\ORM\Repositories\RDB
|
||||
$accountId = $entity->get('accountId');
|
||||
if (empty($accountId)) {
|
||||
$this->unrelate($entity, 'accounts', $entity->getFetched('accountId'));
|
||||
return $result;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +69,7 @@ class Contact extends \Espo\Core\ORM\Repositories\RDB
|
||||
if (empty($accountId)) {
|
||||
$accountId = $entity->getFetched('accountId');
|
||||
if (empty($accountId)) {
|
||||
return $result;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,12 +101,6 @@ class Contact extends \Espo\Core\ORM\Repositories\RDB
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->has('targetListId') && $entity->isNew()) {
|
||||
$this->relate($entity, 'targetLists', $entity->get('targetListId'));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class Lead extends \Espo\Core\ORM\Repositories\RDB
|
||||
{
|
||||
parent::afterSave($entity, $options);
|
||||
|
||||
if ($entity->has('targetListId') && $entity->isNew()) {
|
||||
if ($entity->has('targetListId')) {
|
||||
$this->relate($entity, 'targetLists', $entity->get('targetListId'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,11 +56,28 @@ class Meeting extends \Espo\Core\ORM\Repositories\RDB
|
||||
$usersIds[] = $assignedUserId;
|
||||
$entity->set('usersIds', $usersIds);
|
||||
$hash = $entity->get('usersNames');
|
||||
if ($hash instanceof \stdClass) {
|
||||
if ($hash instanceof \StdClass) {
|
||||
$hash->$assignedUserId = $entity->get('assignedUserName');
|
||||
$entity->set('usersNames', $hash);
|
||||
}
|
||||
}
|
||||
if ($entity->isNew()) {
|
||||
$currentUserId = $this->getEntityManager()->getUser()->id;
|
||||
if (in_array($currentUserId, $usersIds)) {
|
||||
$usersColumns = $entity->get('usersColumns');
|
||||
if (empty($usersColumns)) {
|
||||
$usersColumns = new \StdClass();
|
||||
}
|
||||
if ($usersColumns instanceof \StdClass) {
|
||||
if (!($usersColumns->$currentUserId instanceof \StdClass)) {
|
||||
$usersColumns->$currentUserId = new \StdClass();
|
||||
}
|
||||
if (empty($usersColumns->$currentUserId->status)) {
|
||||
$usersColumns->$currentUserId->status = 'Accepted';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,15 +44,18 @@
|
||||
"Computer": "Informationstechnologie",
|
||||
"Education": "Bildungswesen",
|
||||
"Electronics": "Elektronik",
|
||||
"Energy": "Energieerzeuger",
|
||||
"Entertainment & Leisure": "Freizeit- und Unterhaltungsindustrie",
|
||||
"Finance": "Finanzsektor",
|
||||
"Food & Beverage": "Speisen und Getränke",
|
||||
"Grocery": "Einzelhandel",
|
||||
"Healthcare": "Gesundheitswesen",
|
||||
"Insurance": "Versicherung",
|
||||
"Legal": "Rechtswesen",
|
||||
"Manufacturing": "Produktion",
|
||||
"Publishing": "Medien",
|
||||
"Real Estate": "Immobilien",
|
||||
"Service": "Dienstleistung",
|
||||
"Service": "Service",
|
||||
"Sports": "Sport",
|
||||
"Software": "Software",
|
||||
"Technology": "Technologie",
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
"softBouncedCount": "Soft Bounced",
|
||||
"leadCreatedCount": "Erstellte Interessenten",
|
||||
"revenue": "Umsatz",
|
||||
"revenueConverted": "Umsatz (konvertiert)"
|
||||
"revenueConverted": "Umsatz (konvertiert)",
|
||||
"budget": "Budget"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Kontaktlisten",
|
||||
@@ -24,7 +25,9 @@
|
||||
"contacts": "Kontakte",
|
||||
"leads": "Interessenten",
|
||||
"opportunities": "Verkaufschancen",
|
||||
"campaignLogRecords": "Protokoll"
|
||||
"campaignLogRecords": "Protokoll",
|
||||
"massEmails": "Massen E-Mails",
|
||||
"trackingUrls": "Tracking URLs"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
@@ -47,9 +50,13 @@
|
||||
"Target Lists": "Kontaktlisten",
|
||||
"Statistics": "Statistik",
|
||||
"hard": "hart",
|
||||
"soft": "weich"
|
||||
"soft": "weich",
|
||||
"Unsubscribe": "Abmelden"
|
||||
},
|
||||
"presetFilters": {
|
||||
"active": "Aktiv"
|
||||
},
|
||||
"messages": {
|
||||
"unsubscribed": "Sie wurden erfolgreich von unserem Verteiler entfernt"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"campaign": "Kampagne",
|
||||
"parent": "Zielkontakt",
|
||||
"object": "Objekt",
|
||||
"application": "Applikation"
|
||||
"application": "Applikation",
|
||||
"queueItem": "Warteschlangeneintrag"
|
||||
},
|
||||
"options": {
|
||||
"action": {
|
||||
@@ -20,5 +21,13 @@
|
||||
},
|
||||
"labels": {
|
||||
"All": "Alle"
|
||||
},
|
||||
"presetFilters": {
|
||||
"sent": "Gesendet",
|
||||
"opened": "Geöffnet",
|
||||
"optedOut": "Keine E-Mails",
|
||||
"bounced": "Nicht zustellbar",
|
||||
"clicked": "Geklickt",
|
||||
"leadCreated": "Interessent erstellt"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"fields": {
|
||||
"url": "URL",
|
||||
"urlToUse": "Code zu Einfügen anstelle einer URL",
|
||||
"campaign": "Kampagne"
|
||||
},
|
||||
"links": {
|
||||
"campaign": "Kampagne"
|
||||
},
|
||||
"labels": {
|
||||
"Create CampaignTrackingUrl": "Tracking URL erstellen"
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,21 @@
|
||||
"status": "Status",
|
||||
"account": "Firma",
|
||||
"contact": "Kontakt",
|
||||
"contacts": "Kontakte",
|
||||
"priority": "Priorität",
|
||||
"type": "Typ",
|
||||
"description": "Beschreibung"
|
||||
"description": "Beschreibung",
|
||||
"inboundEmail": "Eingehende E-Mails"
|
||||
},
|
||||
"links": {
|
||||
"inboundEmail": "Eingehende E-Mails",
|
||||
"account": "Firma",
|
||||
"contact": "Kontakt (Primär)",
|
||||
"Contacts": "Kontakte",
|
||||
"meetings": "Meetings",
|
||||
"calls": "Anrufe",
|
||||
"tasks": "Aufgaben",
|
||||
"emails": "E-Mails"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
@@ -33,7 +43,11 @@
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Case": "Fall erstellen"
|
||||
"Create Case": "Fall erstellen",
|
||||
"Close": "Schließen",
|
||||
"Reject": "Ablehnen",
|
||||
"Closed": "Abgeschlossen",
|
||||
"Rejected": "Abgelehnt"
|
||||
},
|
||||
"presetFilters": {
|
||||
"open": "Offen",
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
"cases": "Fälle",
|
||||
"targetLists": "Kontaktlisten",
|
||||
"campaignLogRecords": "Kampagnen Log",
|
||||
"campaign": "Kampagne"
|
||||
"campaign": "Kampagne",
|
||||
"account": "Firma (Primär)",
|
||||
"accounts": "Firmen",
|
||||
"casesPrimary": "Fälle (Primär)"
|
||||
},
|
||||
"labels": {
|
||||
"Create Contact": "Kontakt erstellen"
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Name",
|
||||
"status": "Status",
|
||||
"target": "Zielkontakt",
|
||||
"sentAt": "Sendedatum",
|
||||
"attemptCount": "Versuche",
|
||||
"emailAddress": "E-Mail Adresse",
|
||||
"massEmail": "Massen E-Mails",
|
||||
"isTest": "Ist Test"
|
||||
},
|
||||
"links": {
|
||||
"target": "Zielkontakt",
|
||||
"massEmail": "Massen E-Mails"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Pending": "Schwebend",
|
||||
"Sent": "Gesendet",
|
||||
"Failed": "Fehlgeschlagen"
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
"pending": "Schwebend",
|
||||
"sent": "Gesendet",
|
||||
"failed": "Fehlgeschlagen"
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,10 @@
|
||||
"Document": "Dokument",
|
||||
"DocumentFolder": "Dokumente Ordner",
|
||||
"Campaign": "Kampagne",
|
||||
"TargetList": "Kontaktliste"
|
||||
"TargetList": "Kontaktliste",
|
||||
"MassEmail": "Massen E-Mails",
|
||||
"EmailQueueItem": "E-Mail Warteschlangeneintrag",
|
||||
"CampaignTrackingUrl": "Tracking URL"
|
||||
},
|
||||
"scopeNamesPlural": {
|
||||
"Account": "Firmen",
|
||||
@@ -29,7 +32,10 @@
|
||||
"Document": "Dokumente",
|
||||
"DocumentFolder": "Dokumente Ordner",
|
||||
"Campaign": "Kampagnen",
|
||||
"TargetList": "Kontaktlisten"
|
||||
"TargetList": "Kontaktlisten",
|
||||
"MassEmail": "Massen E-Mails",
|
||||
"EmailQueueItem": "E-Mail Warteschlangeneinträge",
|
||||
"CampaignTrackingUrl": "Tracking URLs"
|
||||
},
|
||||
"dashlets": {
|
||||
"Leads": "Meine Interessenten",
|
||||
@@ -42,7 +48,8 @@
|
||||
"OpportunitiesByStage": "Verkaufschancen nach Verkaufsphase",
|
||||
"OpportunitiesByLeadSource": "Verkaufschancen nach Quelle",
|
||||
"SalesByMonth": "Umsätze nach Monat",
|
||||
"SalesPipeline": "Verkaufspipeline"
|
||||
"SalesPipeline": "Verkaufspipeline",
|
||||
"Activities": "Meine Aktivitäten"
|
||||
},
|
||||
"labels": {
|
||||
"Create InboundEmail": "Eingehende E-Mail erstellen",
|
||||
@@ -56,7 +63,7 @@
|
||||
"Log Call": "Anruf erfassen",
|
||||
"Archive Email": "E-Mail archivieren",
|
||||
"Create Task": "Neue Aufgabe",
|
||||
"Tasks": "Aufgaben"
|
||||
"Tasks": "Aufgaben"
|
||||
},
|
||||
"fields": {
|
||||
"billingAddressCity": "Ort",
|
||||
@@ -68,7 +75,7 @@
|
||||
"addressStreet": "Straße",
|
||||
"addressCountry": "Land",
|
||||
"addressState": "Bundesland/Kanton",
|
||||
"addressPostalCode": "PLZ",
|
||||
"addressPostalCode": "PLZ",
|
||||
"shippingAddressCity": "Ort (Lieferadresse)",
|
||||
"shippingAddressStreet": "Straße (Lieferadresse)",
|
||||
"shippingAddressCountry": "Land (Lieferadresse)",
|
||||
@@ -78,7 +85,7 @@
|
||||
"links": {
|
||||
"contacts": "Kontakte",
|
||||
"opportunities": "Verkaufschancen",
|
||||
"leads": "Interessenten",
|
||||
"leads": "Interessenten",
|
||||
"meetings": "Meetings",
|
||||
"calls": "Anrufe",
|
||||
"tasks": "Aufgaben",
|
||||
@@ -87,7 +94,7 @@
|
||||
"cases": "Fälle",
|
||||
"documents": "Dokumente",
|
||||
"account": "Firma",
|
||||
"opportunity": "Verkaufschance",
|
||||
"opportunity": "Verkaufschance",
|
||||
"contact": "Kontakt",
|
||||
"parent": "Bezieht sich auf"
|
||||
},
|
||||
|
||||
@@ -28,7 +28,10 @@
|
||||
"links": {
|
||||
"targetLists": "Kontaktlisten",
|
||||
"campaignLogRecords": "Kampagnen Log",
|
||||
"campaign": "Kampagne"
|
||||
"campaign": "Kampagne",
|
||||
"createdAccount": "Firma",
|
||||
"createdContact": "Kontakt",
|
||||
"createdOpportunity": "Verkaufschance"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Name",
|
||||
"status": "Status",
|
||||
"storeSentEmails": "Gesendete E-Mails speichern",
|
||||
"startAt": "Startdatum",
|
||||
"fromAddress": "Von Adresse",
|
||||
"fromName": "Von Name",
|
||||
"replyToAddress": "Antwort-an Adresse",
|
||||
"replyToName": "Antwort-an Name",
|
||||
"campaign": "Kampagne",
|
||||
"emailTemplate": "E-Mail Vorlage",
|
||||
"inboundEmail": "E-Mail Konto",
|
||||
"targetLists": "Kontaktlisten"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Kontaktlisten",
|
||||
"queueItems": "Warteschlangeneinträge",
|
||||
"campaign": "Kampagne",
|
||||
"emailTemplate": "E-Mail Vorlage",
|
||||
"inboundEmail": "E-Mail Konto"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Draft": "Entwurf",
|
||||
"Pending": "Schwebend",
|
||||
"In Process": "In Arbeit",
|
||||
"Complete": "Fertig",
|
||||
"Canceled": "Storniert",
|
||||
"Failed": "Fehlgeschlagen"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create MassEmail": "Massen E-Mail erstellen",
|
||||
"Send Test": "Test senden"
|
||||
},
|
||||
"messages": {
|
||||
"selectAtLeastOneTarget": "Zumindest ein Ziel auswählen",
|
||||
"testSent": "Test E-Mail(s) die gesendet werden sollen"
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@
|
||||
},
|
||||
"presetFilters": {
|
||||
"open": "Offen",
|
||||
"won": "Gewonnen"
|
||||
"won": "Gewonnen",
|
||||
"lost": "Lost"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
{
|
||||
|
||||
"options": {
|
||||
"job": {
|
||||
"CheckInboundEmails": "Eingehende E-Mail prüfen",
|
||||
"CheckEmailAccounts": "Persönliche E-Mail Konten prüfen",
|
||||
"SendEmailReminders": "E-Mail Erinnerungen senden"
|
||||
"ProcessMassEmail": "Massen E-Mails senden"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
"accounts": "Firmen",
|
||||
"contacts": "Kontakte",
|
||||
"leads": "Interessenten",
|
||||
"campaigns": "Kampagnen"
|
||||
"campaigns": "Kampagnen",
|
||||
"massEmails": "Massen E-Mails"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
@@ -24,6 +25,7 @@
|
||||
},
|
||||
"labels": {
|
||||
"Create TargetList": "Kontaktliste erstellen",
|
||||
"Opted Out": "Keine E-Mails"
|
||||
"Opted Out": "Keine E-Mails",
|
||||
"Cancel Opt-Out": "Opt-Out zurücksetzen"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,12 +44,15 @@
|
||||
"Computer": "Computer",
|
||||
"Education": "Education",
|
||||
"Electronics": "Electronics",
|
||||
"Energy": "Energy",
|
||||
"Entertainment & Leisure": "Entertainment & Leisure",
|
||||
"Finance": "Finance",
|
||||
"Food & Beverage": "Food & Beverage",
|
||||
"Grocery": "Grocery",
|
||||
"Healthcare": "Healthcare",
|
||||
"Insurance": "Insurance",
|
||||
"Legal": "Legal",
|
||||
"Manufacturing": "Manufacturing",
|
||||
"Publishing": "Publishing",
|
||||
"Real Estate": "Real Estate",
|
||||
"Service": "Service",
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
"softBouncedCount": "Soft Bounced",
|
||||
"leadCreatedCount": "Leads Created",
|
||||
"revenue": "Revenue",
|
||||
"revenueConverted": "revenue (converted)"
|
||||
"revenueConverted": "revenue (converted)",
|
||||
"budget": "Budget"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Target Lists",
|
||||
@@ -24,7 +25,9 @@
|
||||
"contacts": "Contacts",
|
||||
"leads": "Leads",
|
||||
"opportunities": "Opportunities",
|
||||
"campaignLogRecords": "Log"
|
||||
"campaignLogRecords": "Log",
|
||||
"massEmails": "Mass Emails",
|
||||
"trackingUrls": "Tracking URLs"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
@@ -47,9 +50,13 @@
|
||||
"Target Lists": "Target Lists",
|
||||
"Statistics": "Statistics",
|
||||
"hard": "hard",
|
||||
"soft": "soft"
|
||||
"soft": "soft",
|
||||
"Unsubscribe": "Unsubscribe"
|
||||
},
|
||||
"presetFilters": {
|
||||
"active": "Active"
|
||||
},
|
||||
"messages": {
|
||||
"unsubscribed": "You have been unsubscribed from our mailing list."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"campaign": "Campaign",
|
||||
"parent": "Target",
|
||||
"object": "Object",
|
||||
"application": "Application"
|
||||
"application": "Application",
|
||||
"queueItem": "Queue Item"
|
||||
},
|
||||
"options": {
|
||||
"action": {
|
||||
@@ -20,5 +21,13 @@
|
||||
},
|
||||
"labels": {
|
||||
"All": "All"
|
||||
},
|
||||
"presetFilters": {
|
||||
"sent": "Sent",
|
||||
"opened": "Opened",
|
||||
"optedOut": "Opted Out",
|
||||
"bounced": "Bounced",
|
||||
"clicked": "Clicked",
|
||||
"leadCreated": "Lead Created"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"fields": {
|
||||
"url": "URL",
|
||||
"urlToUse": "Code to insert instead of URL",
|
||||
"campaign": "Campaign"
|
||||
},
|
||||
"links": {
|
||||
"campaign": "Campaign"
|
||||
},
|
||||
"labels": {
|
||||
"Create CampaignTrackingUrl": "Create Tracking URL"
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,21 @@
|
||||
"status": "Status",
|
||||
"account": "Account",
|
||||
"contact": "Contact",
|
||||
"contacts": "Contacts",
|
||||
"priority": "Priority",
|
||||
"type": "Type",
|
||||
"description": "Description"
|
||||
"description": "Description",
|
||||
"inboundEmail": "Inbound Email"
|
||||
},
|
||||
"links": {
|
||||
"inboundEmail": "Inbound Email",
|
||||
"account": "Account",
|
||||
"contact": "Contact (Primary)",
|
||||
"Contacts": "Contacts",
|
||||
"meetings": "Meetings",
|
||||
"calls": "Calls",
|
||||
"tasks": "Tasks",
|
||||
"emails": "Emails"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
@@ -33,7 +43,11 @@
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Case": "Create Case"
|
||||
"Create Case": "Create Case",
|
||||
"Close": "Close",
|
||||
"Reject": "Reject",
|
||||
"Closed": "Closed",
|
||||
"Rejected": "Rejected"
|
||||
},
|
||||
"presetFilters": {
|
||||
"open": "Open",
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
"cases": "Cases",
|
||||
"targetLists": "Target Lists",
|
||||
"campaignLogRecords": "Campaign Log",
|
||||
"campaign": "Campaign"
|
||||
"campaign": "Campaign",
|
||||
"account": "Account (Primary)",
|
||||
"accounts": "Accounts",
|
||||
"casesPrimary": "Cases (Primary)"
|
||||
},
|
||||
"labels": {
|
||||
"Create Contact": "Create Contact"
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Name",
|
||||
"status": "Status",
|
||||
"target": "Target",
|
||||
"sentAt": "Date Sent",
|
||||
"attemptCount": "Attempts",
|
||||
"emailAddress": "Email Address",
|
||||
"massEmail": "Mass Email",
|
||||
"isTest": "Is Test"
|
||||
},
|
||||
"links": {
|
||||
"target": "Target",
|
||||
"massEmail": "Mass Email"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Pending": "Pending",
|
||||
"Sent": "Sent",
|
||||
"Failed": "Failed"
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
"pending": "Pending",
|
||||
"sent": "Sent",
|
||||
"failed": "Failed"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user