Compare commits

...

417 Commits
4.4.1 ... 4.7.2

Author SHA1 Message Date
yuri
09e364625d fix formula parser 2017-06-08 16:52:03 +03:00
yuri
35f575ed7f fix array field 2017-06-07 12:06:58 +03:00
yuri
7b0d46b37f travel industry 2017-06-07 11:51:39 +03:00
yuri
f474137b91 fix mention 2017-06-06 14:01:33 +03:00
yuri
7a18d88c50 fix export 2 2017-06-06 12:20:46 +03:00
yuri
8d1c9fe666 fix export 2017-06-06 12:01:19 +03:00
yuri
e6566bccdc fix portal 2017-05-29 13:42:41 +03:00
yuri
14ed7282f3 cleanup 2017-05-29 11:47:50 +03:00
yuri
b13145adce version 2017-05-29 11:40:52 +03:00
yuri
3cfca9845a improve dependencies 2017-05-29 11:40:06 +03:00
yuri
afa8d07bb4 fix notice 2017-05-29 11:35:00 +03:00
yuri
02434e0ca1 css fix 2017-05-26 11:48:34 +03:00
yuri
11f76c507b fix export sheet name 2017-05-25 14:51:11 +03:00
yuri
c68f3eb44d template fixes 2017-05-25 14:22:39 +03:00
yuri
6a1d8dcdca version 2017-05-25 11:44:44 +03:00
yuri
ba358e5847 Merge branch 'hotfix/4.7.1' of ssh://172.20.0.1/var/git/espo/backend into hotfix/4.7.1 2017-05-25 11:40:18 +03:00
yuri
5e174fd5a9 excel export fix 2017-05-25 11:16:58 +03:00
yuri
9af2500292 xsl export fix 2017-05-24 13:41:15 +03:00
yuri
8e9dea260e fix port theme 2017-05-22 15:40:31 +03:00
yunga91
29ed6cb3b0 Fix view name resolving for custom field types in filter action (#546)
* fix view name resolving for custom field types in merge action

* fix view name resolving for custom field types in filter action
2017-05-22 14:36:43 +03:00
yuri
4670bb49e8 excel export by default 2017-05-22 14:15:56 +03:00
yuri
fcc18befc3 excel export fix currency 2017-05-19 17:37:18 +03:00
yuri
52ac9b1621 small fix 2017-05-19 17:14:58 +03:00
yuri
9bca545f01 fix excel temp file name 2017-05-19 15:11:05 +03:00
Taras Machyshyn
80032f8ed7 Correct labels 2017-05-18 17:08:37 +03:00
yuri
a63a690307 field manager: forbid underscore name 2017-05-18 13:24:36 +03:00
yuri
24dc2716f7 fix excel export label 2017-05-18 12:44:30 +03:00
yuri
3f40896374 export fileName 2017-05-18 12:18:31 +03:00
yuri
8d8778b397 lang 2017-05-17 16:07:36 +03:00
yuri
68d3b422cc lang 2017-05-17 15:56:28 +03:00
yuri
145420aaaa fix export noJoin names 2017-05-17 15:31:54 +03:00
yuri
34ee17b7f5 fix notice 2017-05-16 13:45:12 +03:00
yuri
2a0646d1dd fix warning 2017-05-16 12:47:37 +03:00
yuri
52620e84cd skipCreatedBy 2017-05-16 12:21:35 +03:00
yuri
4747113742 lang 2017-05-16 11:34:22 +03:00
yuri
f26d7c6a62 lang 2017-05-16 11:30:43 +03:00
yuri
2e0d8cfd43 hide 2017-05-16 11:12:35 +03:00
yuri
db57c53652 BAM currency 2017-05-16 10:55:27 +03:00
yuri
badf1aec6f fix side panel 2017-05-15 11:38:46 +03:00
yuri
19bb4514df lang 2017-05-12 14:31:32 +03:00
yuri
778be7fea8 Merge branch 'master' of github.com:espocrm/espocrm 2017-05-12 11:22:53 +03:00
yuri
326970bcd4 fix lang 2017-05-12 11:22:42 +03:00
yuri
9411bce8b0 fix sorting field types 2017-05-12 11:12:40 +03:00
yuri
244c1a426b fix model factory 2017-05-12 11:04:36 +03:00
Mauricio Panuncio
b3f9ca8721 Fix and improve translations ES (#538)
* Translate es_ES: Globals. Admin.

* Tickets.

* Emails.

* New translations (missing).

* New translations (missing) II.

* Various.

* Opportunities: Improvement. Self-explanatory names.

* Some small fixes.

* Undo Tickets. Redo Casos.

* Fix: 'Lenguaje' to 'Idioma'.

* Fix some erros in the installation screens.

* Fix some erros in the installation screens II.

* Chamge mod

* Translate. Round 1.

* Translate ES. Stream: Actividades to Historia.

* Translate ES. Lead: Potencial to Posible Cliente.

* Translate ES. Log: Registros.

* Translate ES. Round 2.

* Translate ES. Round 3.

* Translate ES. Round 4.

* Translate ES. New translations.

* Translate ES. Fix bugs.

* Translate ES. Activity: Actividades to Actividades planeadas.

* Translate ES. Hostory: Historia to Historial de aactividades.

* Translate ES. Improvements.

* Fix.

* Traanslate ES.

* Traanslate ES.

* Traanslate ES.

* Fix permissions.

* New translations ES

* Fix and improve translations ES.
2017-05-11 17:55:55 +03:00
yuri
8c66a83054 html cache timestamp 2017-05-10 16:52:56 +03:00
yuri
df6a1f6613 defaults config addition 2017-05-10 14:59:59 +03:00
yuri
1033a926fc v 4.7.0 2017-05-10 14:49:41 +03:00
yuri
d339c04177 field manager: dont allow field name beginning with a number 2017-05-10 12:52:28 +03:00
yuri
edcf0aae84 allow only one attachment multiple field 2017-05-10 12:47:14 +03:00
yuri
20f97caab3 field manager: not allow name same as link 2017-05-10 12:36:50 +03:00
yuri
86be4e7352 Merge branch 'hotfix/4.6.1' 2017-05-10 12:31:50 +03:00
yuri
697e271e66 Merge branch 'hotfix/4.6.1' of ssh://172.20.0.1/var/git/espo/backend into hotfix/4.6.1 2017-05-10 12:31:34 +03:00
yuri
5f74504da8 cleanup changes 2017-05-10 12:06:11 +03:00
yuri
fb3d46d389 attachments fill parentType or relatedId w/o id if entity is not created 2017-05-10 11:35:23 +03:00
yuri
875971fb6e generate password preview 2017-05-10 10:59:04 +03:00
yuri
1939a58f17 stream post storing improvement 2017-05-09 15:57:03 +03:00
yuri
40b3374fdd stream post keep attachments 2017-05-09 15:07:03 +03:00
yuri
c564b1b75a stream: store post content on leave 2017-05-09 12:57:49 +03:00
yuri
c28e73ce3f formula fix 2017-05-08 16:06:47 +03:00
yuri
788a6bfdc3 formula ui fix 2017-05-08 13:32:16 +03:00
yuri
15d1f79115 formula change ui 2017-05-08 13:30:14 +03:00
yuri
bf699d88f7 system jobs 2017-05-08 12:34:07 +03:00
yuri
d7f8e4e050 fix notice 2017-05-08 12:32:49 +03:00
yuri
3872d7897a stream ignoreScopeList fix 2017-05-08 11:46:48 +03:00
yuri
17a1f6ce63 stream ignoreScopeList fix 2017-05-08 11:45:50 +03:00
Mauricio Panuncio
eaa155eff7 Translate es (#536)
* Translate es_ES: Globals. Admin.

* Tickets.

* Emails.

* New translations (missing).

* New translations (missing) II.

* Various.

* Opportunities: Improvement. Self-explanatory names.

* Some small fixes.

* Undo Tickets. Redo Casos.

* Fix: 'Lenguaje' to 'Idioma'.

* Fix some erros in the installation screens.

* Fix some erros in the installation screens II.

* Chamge mod

* Translate. Round 1.

* Translate ES. Stream: Actividades to Historia.

* Translate ES. Lead: Potencial to Posible Cliente.

* Translate ES. Log: Registros.

* Translate ES. Round 2.

* Translate ES. Round 3.

* Translate ES. Round 4.

* Translate ES. New translations.

* Translate ES. Fix bugs.

* Translate ES. Activity: Actividades to Actividades planeadas.

* Translate ES. Hostory: Historia to Historial de aactividades.

* Translate ES. Improvements.

* Fix.

* Traanslate ES.

* Traanslate ES.

* Traanslate ES.

* Fix permissions.
2017-05-08 10:57:45 +03:00
yuri
13fba6d71c Merge branch 'master' of github.com:espocrm/espocrm 2017-05-08 10:56:50 +03:00
yuri
0d423aa349 Merge branch 'hotfix/4.6.1' 2017-05-08 10:56:09 +03:00
yuri
2fca224ba4 fix html 2017-05-08 10:55:47 +03:00
yuri
574f85df46 email template related 2017-05-08 10:42:25 +03:00
yuri
b7176983e2 email template related 2017-05-08 10:42:01 +03:00
Mauricio Panuncio
e8f19ff0dc Translate es (#536)
* Translate es_ES: Globals. Admin.

* Tickets.

* Emails.

* New translations (missing).

* New translations (missing) II.

* Various.

* Opportunities: Improvement. Self-explanatory names.

* Some small fixes.

* Undo Tickets. Redo Casos.

* Fix: 'Lenguaje' to 'Idioma'.

* Fix some erros in the installation screens.

* Fix some erros in the installation screens II.

* Chamge mod

* Translate. Round 1.

* Translate ES. Stream: Actividades to Historia.

* Translate ES. Lead: Potencial to Posible Cliente.

* Translate ES. Log: Registros.

* Translate ES. Round 2.

* Translate ES. Round 3.

* Translate ES. Round 4.

* Translate ES. New translations.

* Translate ES. Fix bugs.

* Translate ES. Activity: Actividades to Actividades planeadas.

* Translate ES. Hostory: Historia to Historial de aactividades.

* Translate ES. Improvements.

* Fix.

* Traanslate ES.

* Traanslate ES.

* Traanslate ES.

* Fix permissions.
2017-05-07 08:13:47 +03:00
yuri
d3cb4607ea orm functions 2017-05-05 15:57:11 +03:00
yuri
8ae0696f07 formula: minute, hour 2017-05-05 13:45:37 +03:00
yuri
299c3c13fc orm: functionList 2017-05-05 13:33:33 +03:00
yuri
a79a8bcef6 orm dayofweek 2017-05-05 12:50:05 +03:00
yuri
2a0dd46b5e formula: date functions 2017-05-05 12:44:27 +03:00
yuri
6c287bc2e2 orm: DATE functions 2017-05-05 11:53:08 +03:00
yuri
7add59ffcb formula: list 2017-05-05 11:03:21 +03:00
yuri
9747c43988 duplicate link new tab 2017-05-04 15:40:39 +03:00
yuri
8b9a0f1437 excel export changes 2017-05-04 14:43:12 +03:00
yuri
1315ca007c fix 2017-05-03 16:37:59 +03:00
yuri
e753d767fc no-currency support 2017-05-03 16:34:25 +03:00
yuri
db893859c2 excel export changes 2017-05-03 16:25:02 +03:00
yuri
16af3d2ad8 currency format 2017-05-03 16:24:47 +03:00
yuri
f334080fe6 metadata currency symbols 2017-05-03 14:20:07 +03:00
yuri
b2acfbed98 email keep attachments on select template option 2017-05-03 12:00:21 +03:00
yuri
2aca6ca28a email keep attachments on select template option 2017-05-03 11:59:12 +03:00
yuri
c96040edec export fixes 2017-05-02 15:30:48 +03:00
yuri
e0ebb44e64 export xslx 2017-05-02 15:14:18 +03:00
yuri
ee1af88f8d fix select manager order file field 2017-05-02 11:27:46 +03:00
yuri
1659e583ea fix select manager order file field 2017-05-02 11:27:27 +03:00
yuri
6f0575d798 Merge branch 'hotfix/4.6.1' of ssh://172.20.0.1/var/git/espo/backend 2017-04-28 17:05:53 +03:00
Taras Machyshyn
ba05c45f47 EntityManager: fixed translated options 2017-04-28 17:02:16 +03:00
yuri
353caf29b3 fix export 2017-04-28 16:40:55 +03:00
yuri
7600d473bb export change 2017-04-28 16:39:26 +03:00
yuri
c9ff48245e export changes 2017-04-28 16:16:44 +03:00
yuri
4ed4a94209 export changes 2017-04-28 15:50:18 +03:00
yuri
c88e01fe75 export populate with list layout 2017-04-28 15:10:40 +03:00
yuri
9e46edce79 fix export 2017-04-28 14:46:39 +03:00
yuri
bae5c67839 exportCollection 2017-04-28 14:44:25 +03:00
yuri
635d5d9c6c tr_TR lang 2017-04-28 13:45:18 +03:00
yuri
65be8c385f formula array includes 2017-04-28 13:36:11 +03:00
yuri
c3d44e2472 orm not subquery prevent too deep 2017-04-28 12:42:08 +03:00
yuri
4a781ed5f4 Merge branch 'hotfix/4.6.1' 2017-04-28 12:34:13 +03:00
yuri
d9995512a1 fix required sign 2017-04-28 12:34:04 +03:00
Taras Machyshyn
6ed2466785 Fixed nginx routing rules 2017-04-28 12:15:01 +03:00
Anthony Andriano
724c74b488 en_US Updates (#525)
* fixed a typo

* updated a few en_US labels to be more natural english
2017-04-28 11:31:19 +03:00
Anthony Andriano
67887c5ba4 update diff to use util instead of sys (#524) 2017-04-28 11:31:05 +03:00
yuri
ea2a0068ed Merge branch 'master' of github.com:espocrm/espocrm 2017-04-28 11:25:25 +03:00
Anthony Andriano
0bfdea5976 en_US Updates (#525)
* fixed a typo

* updated a few en_US labels to be more natural english
2017-04-27 20:04:13 +03:00
Anthony Andriano
305ebc293f update diff to use util instead of sys (#524) 2017-04-27 19:19:58 +03:00
yuri
f17f74672e fix orm 2017-04-27 15:57:39 +03:00
yuri
fcaf184b13 dynamic logic and forumla add field focus 2017-04-27 15:41:51 +03:00
yuri
efe653f1f6 dynamic logic and forumla add field focus 2017-04-27 15:41:24 +03:00
yuri
c1022bf8f3 Merge branch 'hotfix/4.6.1' 2017-04-27 15:01:01 +03:00
yuri
0f4c3988f8 fix class name 2017-04-27 15:00:45 +03:00
yuri
498b7b5679 Merge branch 'hotfix/4.6.1' 2017-04-27 12:36:14 +03:00
yuri
ca445a3cb7 kb ui acl fix 2017-04-27 12:36:02 +03:00
yuri
8a293749e0 fix ORM not 2017-04-27 12:14:22 +03:00
yuri
5c034279e8 Merge branch 'hotfix/4.6.1' 2017-04-27 11:33:31 +03:00
yuri
9460943ad2 escaping fix 2017-04-27 11:33:22 +03:00
yuri
5eaeabe231 ORM: Subqueries IN and NOT 2017-04-26 16:32:24 +03:00
yuri
2202b00600 inlineEditDisabled in clientDefs 2017-04-26 11:35:07 +03:00
Sebastien DOIDO
68ba5a5c4a Improve french translation: Campaign.json + MassEmail.json (#517) 2017-04-24 17:39:35 +03:00
Sebastien DOIDO
e80b490152 Improve french translation: Campaign.json + MassEmail.json (#517) 2017-04-24 16:03:29 +03:00
yuri
380937b644 enum field filters 2017-04-24 15:44:43 +03:00
yuri
ac72305101 Merge branch 'hotfix/4.6.1' 2017-04-24 14:59:27 +03:00
yuri
a41779b0bb fr_FR fixes 2017-04-24 14:58:41 +03:00
yuri
86cdbf24b7 Merge branch 'hotfix/4.6.1' 2017-04-24 12:44:41 +03:00
yuri
5d7bc98088 user detail view: created at field 2017-04-24 12:43:39 +03:00
yuri
1359e8eb2f Merge branch 'hotfix/4.6.1' 2017-04-24 12:32:15 +03:00
yuri
f3a7003444 fr_FR lang 2017-04-24 12:32:05 +03:00
yuri
624f76b1a0 clear local cache improvements 2017-04-24 12:24:30 +03:00
yuri
484ffa071c label fix 2017-04-24 11:40:13 +03:00
Sebastien DOIDO
850fb3cb15 Fix typo to have correct translation (#516) 2017-04-24 11:32:04 +03:00
Sebastien DOIDO
40075ed2e3 Fix typo to have correct translation (#516) 2017-04-24 11:31:26 +03:00
yuri
f68bb4b491 tr_TR lang fix 2017-04-21 11:19:00 +03:00
yuri
473e1109b4 fix import 2017-04-20 15:23:20 +03:00
yuri
c4b8b90ff5 fix css 2017-04-20 12:21:30 +03:00
yuri
70b4017353 tr_TR lang 2017-04-20 11:32:58 +03:00
yuri
e6f7bf4d6c Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend 2017-04-19 16:28:22 +03:00
Taras Machyshyn
69385519d7 Metadata: delete related additional fields in entitiDefs 2017-04-19 16:24:44 +03:00
yuri
235ee7c383 Merge branch 'master' of github.com:espocrm/espocrm 2017-04-19 13:49:21 +03:00
yunga91
a6dba9f09a fix view name resolving for custom field types in merge action (#509) 2017-04-19 13:49:02 +03:00
yuri
f1352430b9 close modal bigger icon 2017-04-18 17:45:08 +03:00
yuri
b9b63a8a7c fix last viewed 2017-04-18 15:50:56 +03:00
yuri
5358bf4a43 fix last viewerd 2017-04-18 15:00:19 +03:00
yuri
1c7a7d8147 template placeholders labels 2017-04-18 14:58:23 +03:00
yuri
ca055e8ca9 css fix 2017-04-18 14:22:33 +03:00
yuri
081c058229 languge field order fix 2017-04-18 13:20:39 +03:00
yuri
a5c941b1b2 zh_CN lang 2017-04-18 13:14:26 +03:00
yuri
d43e63b89e fix checbox css 2 2017-04-18 12:39:47 +03:00
yuri
102886e23d fix firefox checkbox style 2017-04-18 12:06:50 +03:00
yuri
3b8b9e392e fix auth 2017-04-18 12:06:38 +03:00
yuri
226152135d fix portal language 2017-04-18 11:11:18 +03:00
yuri
7f6a5b626e fix last viewed 2017-04-14 16:04:54 +03:00
yuri
c5fa26ffcb portal kb acl published check 2017-04-14 15:12:29 +03:00
yuri
7b2bbcfd05 version 4.6.0 2017-04-13 15:40:10 +03:00
yuri
e5b336d4f3 Merge branch 'master' of github.com:espocrm/espocrm 2017-04-13 15:03:18 +03:00
yuri
2d786d9660 noneOf filter 2017-04-13 15:01:23 +03:00
yuri
a587efddde link multiple filters improvements 2017-04-13 12:56:32 +03:00
yuri
81dd2bc800 link filters changes 2017-04-12 17:20:06 +03:00
tanyalei
b1273176a9 Hooks for afterOptOut, afterCancelOptOut for TargetList (#502)
* Process hooks for optOut, cancelOptOut

* process hook afterOptOut

* process hook afterCancelOptOut

* updateRelation
2017-04-12 16:26:21 +03:00
yuri
46beb8b6b7 uk_UA lang 2017-04-12 15:22:32 +03:00
yuri
264efa2e8d formula number\\round 2017-04-12 14:18:47 +03:00
yuri
f538f05ec3 Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend 2017-04-12 12:16:31 +03:00
yuri
069a50c717 fix hooks 2017-04-12 12:16:19 +03:00
yuri
08f1329868 kb article aclPortal 2017-04-12 12:09:06 +03:00
yuri
e48043c2e8 record list dashlet changes 2017-04-11 16:25:00 +03:00
yuri
024aeb6d01 fix dashlet expoanded layout field 2017-04-11 15:51:48 +03:00
yuri
c79ef63c4d internal scheduled jobs 2017-04-11 15:41:03 +03:00
yuri
54798b94c9 acl: check entity create 2017-04-11 15:40:40 +03:00
yuri
f70f22c503 css changes 2017-04-11 15:28:23 +03:00
yuri
33adc65dac records dashlet layout 2017-04-11 14:42:01 +03:00
yuri
a6541f6f21 fix chart 2 2017-04-11 14:05:49 +03:00
yuri
0b44fee0e5 field manager: forbidden field list 2017-04-11 12:56:16 +03:00
yuri
d03aec270e Merge branch 'master' of github.com:espocrm/espocrm 2017-04-11 12:33:45 +03:00
yuri
08bca7daf7 chart fix 2017-04-11 12:33:30 +03:00
yuri
d5cb1f5c1b useCacheInDeveloperMode 2017-04-11 12:22:31 +03:00
Yuri Kuznetsov
68b16d3de9 Update CONTRIBUTING.md 2017-04-10 16:35:07 +03:00
Taras Machyshyn
daffa60cd4 Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend 2017-04-10 15:56:24 +03:00
Taras Machyshyn
25cb6cdfb3 Installation: correct configuration for nginx server 2017-04-10 15:56:15 +03:00
yuri
7afecc4cdd afterMassRelate, afterUnlinkAll hooks 2017-04-10 12:49:24 +03:00
yuri
0e9373cf5e fix record/list 2017-04-10 12:42:37 +03:00
yuri
7992b78d4e fix naming 2017-04-10 12:19:12 +03:00
yuri
fed5e6ded7 Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend 2017-04-10 12:15:24 +03:00
Taras Machyshyn
82ddd2e562 HookManager: add possibility to define custom hook methods 2017-04-10 12:15:10 +03:00
yuri
1470cea4ed kb article available only in specified portals 2017-04-10 12:01:49 +03:00
yuri
43e8929368 fix kb moveToTop/Bottom 2017-04-10 11:32:02 +03:00
yuri
6db3600a4b Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend 2017-04-10 11:18:09 +03:00
Taras Machyshyn
9b2324755b Fixed wrong php path for Scheduled job in Windows 2017-04-10 10:55:42 +03:00
Taras Machyshyn
dc77b3c73e Added support 'unsetIgnore' 2017-04-10 10:47:10 +03:00
yuri
7627afb7d2 markdown changes 2017-04-07 16:01:42 +03:00
yuri
e68ad81d57 Merge branch 'hotfix/4.5.2' 2017-04-07 14:43:48 +03:00
yuri
73b84d720a fix auth 2017-04-07 14:43:23 +03:00
yuri
0743582ef6 records dashlet fix 2017-04-06 15:54:17 +03:00
yuri
f73d26fcf3 records dashlet sorting 2017-04-06 15:49:16 +03:00
yuri
b1dd9f30fb records dashlet 2017-04-06 15:25:51 +03:00
yuri
27071695cb email: keep list after remove 2017-04-06 13:19:30 +03:00
yuri
1f551b6052 mass email: additional headers 2017-04-06 12:44:56 +03:00
yuri
947ebbb6f5 fix dashboard css 2017-04-05 15:56:18 +03:00
yuri
3a706cad86 cleanup auth tokens 2017-04-05 14:08:17 +03:00
yuri
8cb1709966 document acl portal fix 2017-04-05 13:06:26 +03:00
yuri
7533fc337e preferences changes 2017-04-04 16:56:02 +03:00
yuri
601f908992 action history dev 2017-04-04 13:04:56 +03:00
yuri
ff72489f39 add contact to scope templates acl portal level list 2017-04-04 12:31:57 +03:00
yuri
db442e0769 action history onlt for admin 2017-04-03 14:25:01 +03:00
yuri
189bbd784d last viwed modal click 2017-04-03 14:10:32 +03:00
yuri
2940de57b6 Merge branch 'stable' 2017-04-03 13:55:22 +03:00
yuri
cceb9eccc3 fix license 2017-04-03 12:04:21 +03:00
yuri
410ba24bef Merge branch 'hotfix/4.5.1' 2017-04-03 12:03:15 +03:00
yuri
292e90e6b7 fix formula diff 2017-04-03 12:03:07 +03:00
yuri
3f9b229a9e Merge branch 'hotfix/4.5.1' 2017-04-03 11:30:13 +03:00
yuri
05c2270f36 fix relationship manager not storing has children audited 2017-04-03 11:28:24 +03:00
yuri
f22fdd6724 Merge branch 'hotfix/4.5.1' 2017-04-03 11:14:06 +03:00
yuri
8059669a21 link fields select modal issue 2017-04-03 11:14:00 +03:00
yuri
28a8ad927a Merge branch 'hotfix/4.5.1' 2017-03-31 14:40:27 +03:00
yuri
6f7d27a5fd fix user removal 2017-03-31 14:40:16 +03:00
yuri
d89a173a41 fix warning 2017-03-31 14:01:45 +03:00
yuri
ba5fef320e fix user changePassword method 2017-03-31 13:53:48 +03:00
yuri
a7982acc8f fix login page taborder 2017-03-31 13:30:41 +03:00
yuri
17742fccf1 fix array 2017-03-31 13:26:35 +03:00
yuri
7a2b563cd4 fix array field with empty options 2017-03-31 13:26:20 +03:00
yuri
549984d1ed fix xss 2017-03-31 13:13:27 +03:00
yuri
d9256074fe about tpl change 2017-03-24 16:38:27 +02:00
yuri
97be52a0bc menu change 2017-03-24 16:34:50 +02:00
yuri
26a4d24492 about tpl change 2017-03-24 16:29:00 +02:00
yuri
03dad5a178 action history 2017-03-24 16:19:35 +02:00
yuri
4c0453d0e3 Merge branch 'hotfix/4.5.1' 2017-03-23 12:31:30 +02:00
yuri
1299853961 campaign: subscribe again removes optet out log record 2017-03-23 12:28:25 +02:00
yuri
e6d792ef5a Merge branch 'hotfix/4.5.1' 2017-03-23 11:49:50 +02:00
yuri
e8e8d0d7b2 target list: update count dynamicaly 2017-03-23 11:49:43 +02:00
yuri
cec0c7b374 dynamic logic: multi-enum and array support 2017-03-22 13:22:58 +02:00
yuri
fd73a0b8a5 lang 2017-03-22 11:52:06 +02:00
yuri
120ff8543e language list sorted 2017-03-22 11:12:47 +02:00
yuri
7b8fa73474 Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend 2017-03-22 11:04:35 +02:00
yuri
85164758ce zh_CN lang 2017-03-22 11:04:15 +02:00
yuri
8a38568617 zh_CN lang 2017-03-22 11:03:48 +02:00
Taras Machyshyn
0c9e795dfd Options for tables 2017-03-21 15:20:18 +02:00
yuri
ee1a50aa16 Merge branch 'hotfix/4.5.1' 2017-03-16 12:47:40 +02:00
yuri
a13b6af04a fix modal 2017-03-16 12:47:33 +02:00
yuri
f847535aea small amendments 2017-03-16 12:43:34 +02:00
yuri
b1b03c6dc1 naming fix 2017-03-16 12:26:46 +02:00
yuri
eeb10c6bce fix router navigate back 2017-03-16 12:23:55 +02:00
yuri
05241cefa5 side modal in espo theme 2017-03-15 17:06:28 +02:00
yuri
1861e2cd87 cleanup 2017-03-15 15:20:06 +02:00
yuri
8a17cbe23c mark mandatory fields on edit 2017-03-15 15:18:54 +02:00
yuri
484458c2ba inbound email ui improvement 2 2017-03-15 14:40:56 +02:00
yuri
c62cc15159 inbound email ui fix 2017-03-15 13:29:18 +02:00
yuri
17f8b09782 inbound email ui fix 2017-03-15 13:28:55 +02:00
yuri
9fd05672ae fix 2017-03-13 17:41:36 +02:00
yuri
69d96450da addition to about.tpl 2017-03-13 16:52:51 +02:00
tanyalei
7393040c12 Update datetime-optional.js (#457)
Does not work validating before and after type for field type datetimeOptional, if time wasn't set
2017-03-13 16:45:19 +02:00
yuri
9097e644d4 Merge branch 'master' of https://github.com/espocrm/espocrm 2017-03-13 16:44:12 +02:00
yuri
837b1691d1 showing email address name part 2017-03-13 16:44:00 +02:00
tanyalei
2cdec34062 Update datetime-optional.js (#457)
Does not work validating before and after type for field type datetimeOptional, if time wasn't set
2017-03-13 16:43:20 +02:00
yuri
a33e10e92d mailmimeparser and email parsing imrovements 2017-03-13 16:22:42 +02:00
yuri
86631117a2 fix inline attachment issue 2017-03-13 12:50:50 +02:00
yuri
05dfcf7511 fix image warning 2017-03-13 12:39:38 +02:00
yuri
3e1582bd6b version 2017-03-10 16:49:07 +02:00
yuri
743f348fcf version 2017-03-10 16:19:53 +02:00
yuri
2b2ac2a76d Merge branch 'hotfix/4.5.1' 2017-03-10 15:49:00 +02:00
yuri
a7d2d41b0f da_DK lang 2017-03-10 15:48:26 +02:00
yuri
6ef0081ace nb_NO fixes 2017-03-10 15:44:44 +02:00
yuri
4f3304d55f fix query 2017-03-10 14:24:47 +02:00
yuri
47b6093752 fix query 2017-03-10 14:22:36 +02:00
yuri
ea8d930e56 email: addToPerson improvement 2017-03-10 13:13:05 +02:00
yuri
79f3d86384 contact parent to event 2017-03-10 13:03:36 +02:00
yuri
fff201b7cd parent improvements 2017-03-10 13:02:30 +02:00
yuri
1ad454ce0b fix email address 2017-03-10 12:33:22 +02:00
yuri
e090fe699b new actions for unknown email addresses 2017-03-10 12:32:14 +02:00
yuri
f677b5614b tasks stream 2017-03-09 16:02:57 +02:00
yuri
f7b240e6a9 fix send email not read 2017-03-09 13:04:24 +02:00
yuri
ea3a60aaf7 email address tpl fix 2017-03-09 12:53:38 +02:00
yuri
6a7cfa58ae email import: inline attachment issue 2017-03-09 12:37:53 +02:00
yuri
482f0cc314 dashlet chart color 2017-03-07 11:06:59 +02:00
yuri
28ada61f3d internal post title 2017-03-07 10:58:04 +02:00
yuri
7057210e90 next number table locking 2017-03-06 17:32:54 +02:00
yuri
8c5bc59c45 fix lang 2017-03-06 15:35:53 +02:00
yuri
b7370ff238 activities panel: check read access 2017-03-06 12:49:03 +02:00
yuri
fb36f769d9 SelectManager: accessNo 2017-03-06 12:37:34 +02:00
yuri
f07b728851 nb_NO lang 2017-03-06 11:01:28 +02:00
yuri
7d4ada7ec2 fix portal user creation 2017-03-02 16:28:05 +02:00
yuri
1c31a6689f fix event duration order 2017-03-02 12:41:21 +02:00
yuri
a839144796 hide reminders from list view layout 2017-03-02 12:21:16 +02:00
yuri
87cbe603d2 fix lang 2017-03-02 12:00:53 +02:00
yuri
ec96916013 Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend 2017-03-02 11:44:52 +02:00
yuri
2c811a4faa integration form fix 2017-03-02 11:43:11 +02:00
yuri
6e089c1e25 change stream post tpl 2017-03-02 11:03:30 +02:00
yuri
2e203341b7 dynamic logic: foreign fields 2017-03-02 10:30:21 +02:00
yuri
5bea143bf0 labels 2017-03-02 10:22:49 +02:00
yuri
732494e251 import: added time format with seconds 2017-03-01 16:57:18 +02:00
Taras Machyshyn
39e1303cbe Schema Converter improvements 2017-03-01 16:17:52 +02:00
yuri
62c3549004 label fix 2017-03-01 15:20:40 +02:00
yuri
9bcc942f0f change formula metadata 2017-03-01 13:04:28 +02:00
yuri
e34ee34d7b fix formula function insertText 2017-03-01 12:25:42 +02:00
yuri
dedef4b36f array: none if empty 2017-03-01 12:18:54 +02:00
yuri
e6f6e0fcf1 email performance improvement 2017-03-01 12:07:52 +02:00
yuri
11a9e2ab9c mark notification read if email is read 2017-03-01 12:05:50 +02:00
yuri
9077542f61 fix email inbound 2017-03-01 12:03:31 +02:00
yuri
cb6faaa769 fix email back 2017-02-28 15:55:28 +02:00
yuri
a209d5aaaf link multiple if not set then show dots 2017-02-27 15:17:30 +02:00
yuri
767cdc75ee fix css 2017-02-27 14:03:44 +02:00
yuri
3eef0e088a fix modal backdrop 2017-02-27 11:59:36 +02:00
yuri
1e5ef6a070 fix text field 2017-02-27 11:56:43 +02:00
yuri
a2edc3cf4e theme changes 2017-02-24 12:38:42 +02:00
yuri
9a5dc7b4d1 reduntancy fix 2017-02-24 12:17:19 +02:00
yuri
7b0fd40d3e fix modal 2017-02-24 12:11:25 +02:00
yuri
169df31cab css fix 2017-02-24 11:20:56 +02:00
yuri
44b0ba2f33 fix array field int issue 2017-02-23 16:15:34 +02:00
yuri
8d70956607 Merge branch 'master' of https://github.com/espocrm/espocrm 2017-02-23 15:59:12 +02:00
ayman-alkom
5ad20c8666 fix variable name (#426) 2017-02-23 15:58:48 +02:00
yuri
790d4a88b5 de_DE additions 2017-02-23 14:24:13 +02:00
yuri
b72ac42068 fr_FR langauge 2017-02-23 13:30:38 +02:00
yuri
0a379be049 version 4.5.0 2017-02-23 12:33:22 +02:00
yuri
e0e08a1c17 Merge branch 'hotfix/4.4.2' 2017-02-23 11:28:05 +02:00
yuri
0d825120bb notifications to portal users fix 2017-02-23 11:27:42 +02:00
yuri
7b81b66b76 formula: number abs 2017-02-22 15:38:50 +02:00
yuri
d39f4e2533 forumle: datetime diff 2017-02-22 15:31:36 +02:00
yuri
598a2f9f05 fix 2017-02-22 13:09:07 +02:00
yuri
ce9089b838 date time format 2017-02-22 13:06:10 +02:00
yuri
45b06fc154 stream: auto-follow after posting 2017-02-22 11:38:39 +02:00
yuri
f44177a994 Merge branch 'hotfix/4.4.2' 2017-02-21 17:11:41 +02:00
yuri
d91b13a7c1 Merge branch 'hotfix/4.4.2' of ssh://172.20.0.1/var/git/espo/backend into hotfix/4.4.2 2017-02-21 17:11:08 +02:00
Taras Machyshyn
bd1894322c Slim: fixed a notice 2017-02-21 17:10:16 +02:00
yuri
90874535ea Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend 2017-02-21 17:06:23 +02:00
yuri
8c919dbca4 Merge branch 'hotfix/4.4.2' 2017-02-21 17:06:14 +02:00
yuri
05223c5272 Merge branch 'hotfix/4.4.2' of ssh://172.20.0.1/var/git/espo/backend into hotfix/4.4.2 2017-02-21 17:05:52 +02:00
yuri
afee6d564b select manager textFilterUseContainsAttributeList 2017-02-21 17:04:47 +02:00
Taras Machyshyn
b4e879a369 FieldManager: improved storing logic 2017-02-21 16:26:23 +02:00
yuri
de4d96e260 event template set held action 2017-02-21 15:40:05 +02:00
yuri
89056f61c2 add consulting industry 2017-02-21 12:55:18 +02:00
yuri
afac29151c account filter website 2017-02-21 12:44:35 +02:00
Taras Machyshyn
e54430fb1b Merge branch 'hotfix/4.4.2' 2017-02-20 16:19:23 +02:00
tanyalei
7d8736b98c Creating Target List from Campaign Log not working in php7
creating a target list from the log bug fix(for mysql 5.7+)
2017-02-20 15:00:55 +02:00
tanyalei
216e9419d4 Creating Target List from Campaign Log not working in php7
creating a target list from the log bug fix(for mysql 5.7+)
2017-02-20 14:59:02 +02:00
yuri
359fdd4dab Merge branch 'hotfix/4.4.2' 2017-02-20 11:44:32 +02:00
yuri
2044a87630 fix last quarter filter 2017-02-20 11:44:24 +02:00
yuri
171feed28e global search mouseup fix 2017-02-20 11:10:58 +02:00
yuri
92dbbbd390 Merge branch 'master' of https://github.com/espocrm/espocrm 2017-02-17 16:24:04 +02:00
yuri
3166cb862e inbound email teams field 2017-02-17 12:41:04 +02:00
Taras Machyshyn
b606cb2e04 Fixed warnings in Slim 2017-02-17 11:10:29 +02:00
tanyalei
724ef00d52 clientDefs view of entities for convert (#416) 2017-02-16 21:41:15 +02:00
yuri
0b7857b495 self assign 2017-02-16 16:22:13 +02:00
yuri
a150eb7f0e fix email notification 2017-02-16 13:35:21 +02:00
yuri
4cb21a4fdb Merge branch 'hotfix/4.4.2' 2017-02-16 13:23:43 +02:00
yuri
46e13b0269 Merge branch 'hotfix/4.4.2' of ssh://172.20.0.1/var/git/espo/backend into hotfix/4.4.2 2017-02-16 13:23:32 +02:00
yuri
d4d5138991 fix sorting alphabeetically 2017-02-16 13:23:17 +02:00
yuri
9fd00d9f0a inbound email: reply to not required 2017-02-16 13:16:23 +02:00
yuri
9361938285 Injectable factory && Case: notifications replyToAddress 2017-02-16 13:00:11 +02:00
yuri
cb054b2f2b fix email email address 2017-02-16 12:41:58 +02:00
yuri
f8ff6e6cf5 Merge branch 'hotfix/4.4.2' 2017-02-16 10:56:59 +02:00
yuri
918c1b2114 fix formula resize issue 2017-02-16 10:56:51 +02:00
Taras Machyshyn
2026bcb021 Fixed field manager notices 2017-02-16 10:46:47 +02:00
Taras Machyshyn
ce5393155a Fixed merge method 2017-02-16 10:06:16 +02:00
Taras Machyshyn
6f4b752b10 Fixed merge method 2017-02-15 12:45:31 +02:00
yuri
2a5a453517 Merge branch 'hotfix/4.4.2' 2017-02-14 17:07:05 +02:00
yuri
191bba7afc fix notice 2017-02-14 17:06:54 +02:00
yuri
f50d2ef9e3 fix notice 2017-02-14 16:59:38 +02:00
yuri
1ad744d151 fix source list 2017-02-14 16:49:40 +02:00
yuri
ba0f86c8d4 attachment source list config check 2017-02-14 13:42:43 +02:00
yuri
372c84bfa3 file: sourceList 2017-02-14 12:33:28 +02:00
yuri
6ec18950e4 fix email user sent not added to users 2017-02-14 12:07:37 +02:00
yuri
6c3168a356 Merge branch 'hotfix/4.4.2' 2017-02-14 11:18:18 +02:00
yuri
109ee17a47 formula: parentName 2017-02-14 11:17:35 +02:00
yuri
21702b3c34 Merge branch 'hotfix/4.4.2' 2017-02-10 15:55:39 +02:00
yuri
159a2ee99d fix target list opted out count 2017-02-10 15:55:28 +02:00
yuri
d6151d33b4 ditch document source 2017-02-10 15:36:01 +02:00
yuri
2217e03fa8 file storage: download url 2017-02-10 15:28:52 +02:00
yuri
794c7eb523 fix document download link 2017-02-10 15:27:38 +02:00
yuri
98f61c0c4b fix css 2017-02-10 14:54:59 +02:00
yuri
5f5a450d95 css fix 2017-02-10 13:21:25 +02:00
yuri
0ba9679a75 confirm additions 2017-02-10 13:10:23 +02:00
yuri
85e60d4e32 attachment storage additions 2017-02-10 12:59:49 +02:00
yuri
a074b8a214 htmlizer fix 2017-02-09 16:01:04 +02:00
yuri
ac593c1d3d fix email queue 2 2017-02-09 15:39:34 +02:00
yuri
170e62bc8b fix email queue 2 2017-02-09 15:39:17 +02:00
yuri
5d19ae42dc fix email queue 2017-02-09 15:24:34 +02:00
yuri
9f3fdd01bf fix email queue 2017-02-09 15:24:06 +02:00
yuri
65e94e237d metadata getAllForFrontend 2017-02-09 15:05:11 +02:00
yuri
7935bc59fe fix sysiwyg 2017-02-09 14:31:40 +02:00
yuri
f49677b5c0 file storage manager 2017-02-09 14:29:28 +02:00
yuri
b69f829a3e import: timezone 2017-02-08 14:42:20 +02:00
yuri
13dfc90a1b import tpl fix 2017-02-08 13:46:35 +02:00
yuri
6d49d39480 layout manager confirm 2017-02-08 13:35:32 +02:00
yuri
f473ea9cea dashlet remove confirm 2017-02-08 13:34:06 +02:00
yuri
db8536ac55 phone strikestrough 2017-02-08 12:37:13 +02:00
yuri
e402745a86 change detailSmall layouts 2017-02-08 12:20:14 +02:00
yuri
abcaaddc2f fix wysiwyg destroying 2017-02-08 12:00:53 +02:00
yuri
3ac375c95c confirm change 2017-02-08 11:32:25 +02:00
yuri
56f65e0fc0 ui dialog 2017-02-07 16:30:55 +02:00
yuri
471df0034e css changes 2017-02-07 12:50:40 +02:00
yuri
a1b3be9ef3 Merge branch 'hotfix/4.4.2' 2017-02-07 11:32:36 +02:00
yuri
c4f70482ac fix email folder navigate back 2017-02-07 11:31:53 +02:00
yuri
31a8fa387d fix autocomplete 2017-02-07 10:48:45 +02:00
yuri
a0d6cb9be4 fix wysywyg modal 2017-02-07 10:34:53 +02:00
yuri
4586d26bd6 css fix 2017-02-06 17:41:52 +02:00
yuri
1609adc766 modal new style 2017-02-06 17:23:05 +02:00
yuri
aa0a9cf708 Merge branch 'hotfix/4.4.2' 2017-02-06 11:44:04 +02:00
yuri
d7dfe5fea4 email reply head text change 2017-02-06 11:43:47 +02:00
yuri
340ed5acec formula fix 2017-02-06 10:43:51 +02:00
yuri
7ec3e38e6d version 2017-02-03 15:53:53 +02:00
yuri
879bf13809 Merge branch 'stable' 2017-02-03 15:05:02 +02:00
yuri
b44bbaffa2 Merge branch 'hotfix/4.4.1' 2017-02-02 12:44:12 +02:00
yuri
4c562cb603 Merge branch 'hotfix/4.4.1' 2017-02-02 11:59:19 +02:00
yuri
8eb2be46ca Merge branch 'hotfix/4.4.1' 2017-02-02 11:25:53 +02:00
yuri
cd7571387c fix formula field 2017-02-01 15:55:15 +02:00
yuri
1b3496edd9 formula fix 2017-02-01 12:11:49 +02:00
yuri
356da4e70d Merge branch 'hotfix/4.4.1' 2017-02-01 12:06:06 +02:00
yuri
f3deffb3f6 year 2017 2017-02-01 11:43:36 +02:00
yuri
8398cc4364 fix timeline 2017-02-01 11:14:18 +02:00
yuri
6ddda814c0 Merge branch 'hotfix/4.4.1' 2017-01-31 15:30:34 +02:00
yuri
76ffa2def9 duration sortable 2017-01-31 13:24:05 +02:00
yuri
2fdc0a3a93 Merge branch 'master' of https://github.com/espocrm/espocrm 2017-01-31 12:23:12 +02:00
Alasdair Campbell
0dcc8d08d1 Removed executable permission set on stub file data/.data (#386) 2017-01-30 13:15:32 +02:00
990 changed files with 32048 additions and 7150 deletions

View File

@@ -1,3 +1,9 @@
## Pull Requests
Before we can merge your pull request you need to accept our CLA [here](https://github.com/espocrm/cla). It's very simple to do.
[Code Style Guidelines](https://github.com/espocrm/espocrm/wiki/Code-Style-Guidelines).
[Code Style Guidelines](https://github.com/espocrm/espocrm/wiki/Code-Style-Guidelines).
## Issues
We don't provide developer help or any kind of support on github. Please use our [forum](http://forum.espocrm.com/) for this.

View File

@@ -0,0 +1,42 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Acl;
use \Espo\Entities\User as EntityUser;
use \Espo\ORM\Entity;
class ActionHistoryRecord extends \Espo\Core\Acl\Base
{
public function checkIsOwner(EntityUser $user, Entity $entity)
{
return $entity->get('userId') === $user->id;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Acl;
use \Espo\Entities\User as EntityUser;
use \Espo\ORM\Entity;
class ScheduledJob extends \Espo\Core\Acl\Base
{
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
{
if ($entity->get('isInternal')) return false;
return $this->checkEntity($user, $entity, $data, 'read');
}
public function checkEntityEdit(EntityUser $user, Entity $entity, $data)
{
if ($entity->get('isInternal')) return false;
return $this->checkEntity($user, $entity, $data, 'edit');
}
public function checkEntityDelete(EntityUser $user, Entity $entity, $data)
{
if ($entity->get('isInternal')) return false;
return $this->checkEntity($user, $entity, $data, 'delete');
}
public function checkEntityCreate(EntityUser $user, Entity $entity, $data)
{
if ($entity->get('isInternal')) return false;
return $this->checkEntity($user, $entity, $data, 'create');
}
}

View File

@@ -0,0 +1,71 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
class ActionHistoryRecord extends \Espo\Core\Controllers\Record
{
public function actionUpdate($params, $data, $request)
{
throw new Forbidden();
}
public function actionCreate($params, $data, $request)
{
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, $request)
{
throw new Forbidden();
}
public function actionRemoveLink($params, $data, $request)
{
throw new Forbidden();
}
public function actionMassDelete($params, $data, $request)
{
throw new Forbidden();
}
}

View File

@@ -63,7 +63,7 @@ class Admin extends \Espo\Core\Controllers\Base
{
$scheduledJob = $this->getContainer()->get('scheduledJob');
return $scheduledJob->getAllNamesOnly();
return $scheduledJob->getAvailableList();
}
public function postActionUploadUpgradePackage($params, $data)

View File

@@ -65,6 +65,9 @@ class App extends \Espo\Core\Controllers\Base
$settings->$item = $this->getConfig()->get($item);
}
unset($userData['authTokenId']);
unset($userData['password']);
return array(
'user' => $userData,
'acl' => $this->getAcl()->getMap(),

View File

@@ -54,7 +54,7 @@ class Attachment extends \Espo\Core\Controllers\Record
$attachment = $this->getEntityManager()->getEntity('Attachment');
$this->getEntityManager()->saveEntity($attachment);
$this->getContainer()->get('fileManager')->putContents('data/upload/' . $attachment->id, $contents);
$this->getContainer()->get('fileStorageManager')->putContents($attachment, $contents);
return array(
'attachmentId' => $attachment->id

View File

@@ -42,20 +42,37 @@ class AuthToken extends \Espo\Core\Controllers\Record
public function actionUpdate($params, $data, $request)
{
throw new Forbidden();
}
public function actionCreate($params, $data, $request)
{
throw new Forbidden();
}
public function actionListLinked($params, $data, $request)
{
if (
is_array($data) &&
array_key_exists('isActive', $data) &&
$data['isActive'] === false &&
count(array_keys($data)) === 1)
{
return parent::actionUpdate($params, $data, $request);
}
throw new Forbidden();
}
public function actionMassUpdate($params, $data, $request)
{
if (empty($data['attributes'])) {
throw new BadRequest();
}
$attributes = $data['attributes'];
if (
is_object($attributes) &&
isset($attributes->isActive) &&
$attributes->isActive === false &&
count(array_keys(get_object_vars($attributes))) === 1
) {
return parent::actionMassUpdate($params, $data, $request);
}
throw new Forbidden();
}
public function actionCreate($params, $data, $request)
{
throw new Forbidden();
}

View File

@@ -25,7 +25,7 @@
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
************************************************************************/
namespace Espo\Controllers;
@@ -34,17 +34,19 @@ use \Espo\Core\Exceptions\Error;
class EmailTemplate extends \Espo\Core\Controllers\Record
{
public function actionParse($params, $data, $request)
{
{
$id = $request->get('id');
$emailAddress = $request->get('emailAddress');
if (empty($id)) {
throw new Error();
}
return $this->getRecordService()->parse($id, array(
'emailAddress' => $request->get('emailAddress'),
'parentType' => $request->get('parentType'),
'parentId' => $request->get('parentId'),
'relatedType' => $request->get('relatedType'),
'relatedId' => $request->get('relatedId')
), true);
}

View File

@@ -29,10 +29,10 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Error,
\Espo\Core\Exceptions\Forbidden,
\Espo\Core\Exceptions\NotFound,
\Espo\Core\Exceptions\BadRequest;
use Espo\Core\Exceptions\Error;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\NotFound;
use Espo\Core\Exceptions\BadRequest;
class FieldManager extends \Espo\Core\Controllers\Base
{
@@ -49,7 +49,7 @@ class FieldManager extends \Espo\Core\Controllers\Base
throw new BadRequest();
}
$data = $this->getContainer()->get('fieldManager')->read($params['name'], $params['scope']);
$data = $this->getContainer()->get('fieldManager')->read($params['scope'], $params['name']);
if (!isset($data)) {
throw new BadRequest();
@@ -65,16 +65,16 @@ class FieldManager extends \Espo\Core\Controllers\Base
}
$fieldManager = $this->getContainer()->get('fieldManager');
$fieldManager->create($data['name'], $data, $params['scope']);
$fieldManager->create($params['scope'], $data['name'], $data);
try {
$this->getContainer()->get('dataManager')->rebuild($params['scope']);
} catch (Error $e) {
$fieldManager->delete($data['name'], $params['scope']);
$fieldManager->delete($params['scope'], $data['name']);
throw new Error($e->getMessage());
}
return $fieldManager->read($data['name'], $params['scope']);
return $fieldManager->read($params['scope'], $data['name']);
}
public function putActionUpdate($params, $data)
@@ -84,7 +84,7 @@ class FieldManager extends \Espo\Core\Controllers\Base
}
$fieldManager = $this->getContainer()->get('fieldManager');
$fieldManager->update($params['name'], $data, $params['scope']);
$fieldManager->update($params['scope'], $params['name'], $data);
if ($fieldManager->isChanged()) {
$this->getContainer()->get('dataManager')->rebuild($params['scope']);
@@ -92,7 +92,7 @@ class FieldManager extends \Espo\Core\Controllers\Base
$this->getContainer()->get('dataManager')->clearCache();
}
return $fieldManager->read($params['name'], $params['scope']);
return $fieldManager->read($params['scope'], $params['name']);
}
public function deleteActionDelete($params, $data)
@@ -101,11 +101,11 @@ class FieldManager extends \Espo\Core\Controllers\Base
throw new BadRequest();
}
$res = $this->getContainer()->get('fieldManager')->delete($params['name'], $params['scope']);
$result = $this->getContainer()->get('fieldManager')->delete($params['scope'], $params['name']);
$this->getContainer()->get('dataManager')->rebuildMetadata();
return $res;
return $result;
}
public function postActionResetToDefault($params, $data)
@@ -114,7 +114,7 @@ class FieldManager extends \Espo\Core\Controllers\Base
throw new BadRequest();
}
$this->getContainer()->get('fieldManager')->resetToDefault($data['name'], $data['scope']);
$this->getContainer()->get('fieldManager')->resetToDefault($data['scope'], $data['name']);
$this->getContainer()->get('dataManager')->rebuildMetadata();

View File

@@ -68,9 +68,9 @@ class Import extends \Espo\Core\Controllers\Record
throw new BadRequest();
}
protected function getFileManager()
protected function getFileStorageManager()
{
return $this->getContainer()->get('fileManager');
return $this->getContainer()->get('fileStorageManager');
}
protected function getEntityManager()
@@ -92,7 +92,7 @@ class Import extends \Espo\Core\Controllers\Record
$attachment->set('name', 'import-file.csv');
$this->getEntityManager()->saveEntity($attachment);
$this->getFileManager()->putContents('data/upload/' . $attachment->id, $contents);
$this->getFileStorageManager()->putContents($attachment, $contents);
return array(
'attachmentId' => $attachment->id
@@ -167,12 +167,18 @@ class Import extends \Espo\Core\Controllers\Record
throw new BadRequest();
}
$timezone = 'UTC';
if (isset($data['timezone'])) {
$timezone = $data['timezone'];
}
$importParams = array(
'headerRow' => !empty($data['headerRow']),
'fieldDelimiter' => $data['fieldDelimiter'],
'textQualifier' => $data['textQualifier'],
'dateFormat' => $data['dateFormat'],
'timeFormat' => $data['timeFormat'],
'timezone' => $timezone,
'personNameFormat' => $data['personNameFormat'],
'decimalMark' => $data['decimalMark'],
'currency' => $data['currency'],

View File

@@ -0,0 +1,46 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
class LastViewed extends \Espo\Core\Controllers\Base
{
public function getActionIndex($params, $data, $request)
{
$result = $this->getServiceFactory()->create('LastViewed')->get();
return [
'total' => $result['total'],
'list' => isset($result['collection']) ? $result['collection']->toArray() : $result['list']
];
}
}

View File

@@ -33,11 +33,10 @@ use \Espo\Core\Exceptions\Forbidden;
class Metadata extends \Espo\Core\Controllers\Base
{
public function actionRead($params, $data)
{
$data = $this->getMetadata()->getAll();
unset($data['formula']);
return $data;
return $this->getMetadata()->getAllForFrontend();
}
public function getActionGet($params, $data, $request)

View File

@@ -69,6 +69,11 @@ class Acl
return $this->getAclManager()->get($this->getUser(), $permission);
}
public function checkReadNo($scope)
{
return $this->getAclManager()->checkReadNo($this->getUser(), $scope);
}
public function checkReadOnlyTeam($scope)
{
return $this->getAclManager()->checkReadOnlyTeam($this->getUser(), $scope);

View File

@@ -106,6 +106,14 @@ class Base implements Injectable
return $data->read === 'team';
}
public function checkReadNo(User $user, $data)
{
if (empty($data) || !is_object($data) || !isset($data->read)) {
return false;
}
return $data->read === 'no';
}
public function checkReadOnlyOwn(User $user, $data)
{
if (empty($data) || !is_object($data) || !isset($data->read)) {

View File

@@ -36,7 +36,7 @@ use \Espo\Entities\User;
use \Espo\Core\Utils\Config;
use \Espo\Core\Utils\Metadata;
use \Espo\Core\Utils\FieldManager;
use \Espo\Core\Utils\FieldManagerUtil;
use \Espo\Core\Utils\File\Manager as FileManager;
class Table
@@ -77,7 +77,7 @@ class Table
protected $forbiddenFieldsCache = array();
public function __construct(User $user, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManager $fieldManager = null)
public function __construct(User $user, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManagerUtil $fieldManager = null)
{
$this->data = (object) [
'table' => (object) [],

View File

@@ -107,7 +107,7 @@ class AclManager
$config = $this->getContainer()->get('config');
$fileManager = $this->getContainer()->get('fileManager');
$metadata = $this->getContainer()->get('metadata');
$fieldManager = $this->getContainer()->get('fieldManager');
$fieldManager = $this->getContainer()->get('fieldManagerUtil');
$this->tableHashMap[$key] = new $this->tableClassName($user, $config, $fileManager, $metadata, $fieldManager);
}
@@ -133,6 +133,15 @@ class AclManager
return $this->getTable($user)->get($permission);
}
public function checkReadNo(User $user, $scope)
{
if ($user->isAdmin()) {
return false;
}
$data = $this->getTable($user)->getScopeData($scope);
return $this->getImplementation($scope)->checkReadNo($user, $data);
}
public function checkReadOnlyTeam(User $user, $scope)
{
if ($user->isAdmin()) {

View File

@@ -37,7 +37,7 @@ use \Espo\Entities\Portal;
use \Espo\Core\Utils\Config;
use \Espo\Core\Utils\Metadata;
use \Espo\Core\Utils\FieldManager;
use \Espo\Core\Utils\FieldManagerUtil;
use \Espo\Core\Utils\File\Manager as FileManager;
class Table extends \Espo\Core\Acl\Table
@@ -52,7 +52,7 @@ class Table extends \Espo\Core\Acl\Table
protected $valuePermissionList = [];
public function __construct(User $user, Portal $portal, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManager $fieldManager = null)
public function __construct(User $user, Portal $portal, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManagerUtil $fieldManager = null)
{
if (empty($portal)) {
throw new Error("No portal was passed to AclPortal\\Table constructor.");

View File

@@ -128,6 +128,14 @@ class Container
return new \Espo\Core\Utils\Api\Slim();
}
protected function loadFileStorageManager()
{
return new \Espo\Core\FileStorage\Manager(
$this->get('metadata')->get(['app', 'fileStorage', 'implementationClassNameMap']),
$this
);
}
protected function loadFileManager()
{
return new \Espo\Core\Utils\File\Manager(
@@ -327,6 +335,13 @@ class Container
);
}
protected function loadFieldManagerUtil()
{
return new \Espo\Core\Utils\FieldManagerUtil(
$this->get('metadata')
);
}
protected function loadThemeManager()
{
return new \Espo\Core\Utils\ThemeManager(
@@ -343,6 +358,13 @@ class Container
);
}
protected function loadInjectableFactory()
{
return new \Espo\Core\InjectableFactory(
$this
);
}
public function setUser(\Espo\Entities\User $user)
{
$this->set('user', $user);

View File

@@ -67,7 +67,7 @@ class Record extends Base
public function actionRead($params, $data, $request)
{
$id = $params['id'];
$entity = $this->getRecordService()->getEntity($id);
$entity = $this->getRecordService()->readEntity($id);
if (empty($entity)) {
throw new NotFound();
@@ -258,6 +258,14 @@ class Record extends Base
$params['attributeList'] = $data['attributeList'];
}
if (isset($data['fieldList'])) {
$params['fieldList'] = $data['fieldList'];
}
if (isset($data['format'])) {
$params['format'] = $data['format'];
}
return array(
'id' => $this->getRecordService()->export($params)
);

View File

@@ -59,6 +59,8 @@ class DataManager
$result &= $this->rebuildDatabase($entityList);
$this->rebuildScheduledJobs();
return $result;
}
@@ -121,6 +123,40 @@ class DataManager
return empty($ormData) ? false : true;
}
public function rebuildScheduledJobs()
{
$metadata = $this->getContainer()->get('metadata');
$entityManager = $this->getContainer()->get('entityManager');
$jobs = $metadata->get(['entityDefs', 'ScheduledJob', 'jobs'], array());
foreach ($jobs as $jobName => $defs) {
if ($jobName && !empty($defs['isSystem']) && !empty($defs['scheduling'])) {
if (!$entityManager->getRepository('ScheduledJob')->where(array(
'job' => $jobName,
'status' => 'Active',
'scheduling' => $defs['scheduling']
))->findOne()) {
$job = $entityManager->getRepository('ScheduledJob')->where(array(
'job' => $jobName
))->findOne();
if ($job) {
$entityManager->removeEntity($job);
}
$job = $entityManager->getEntity('ScheduledJob');
$job->set(array(
'job' => $jobName,
'status' => 'Active',
'scheduling' => $defs['scheduling'],
'isInternal' => true,
'name' => $jobName
));
$entityManager->saveEntity($job);
}
}
}
}
/**
* Update cache timestamp
*

View File

@@ -0,0 +1,65 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Export;
use \Espo\Core\Exceptions\Error;
class Csv extends \Espo\Core\Injectable
{
protected $dependencyList = [
'config',
'preferences'
];
public function process($entityType, $params, $dataList)
{
if (!is_array($params['attributeList'])) {
throw new Error();
}
$attributeList = $params['attributeList'];
$delimiter = $this->getInjection('preferences')->get('exportDelimiter');
if (empty($delimiter)) {
$delimiter = $this->getInjection('config')->get('exportDelimiter', ';');
}
$fp = fopen('php://temp', 'w');
fputcsv($fp, $attributeList, $delimiter);
foreach ($dataList as $row) {
fputcsv($fp, $row, $delimiter);
}
rewind($fp);
$csv = stream_get_contents($fp);
fclose($fp);
return $csv;
}
}

View File

@@ -0,0 +1,449 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Export;
use \Espo\ORM\Entity;
use \Espo\Core\Exceptions\Error;
class Xlsx extends \Espo\Core\Injectable
{
protected $dependencyList = [
'language',
'metadata',
'config',
'dateTime',
'entityManager',
'fileStorageManager',
'fileManager'
];
protected function getConfig()
{
return $this->getInjection('config');
}
protected function getMetadata()
{
return $this->getInjection('metadata');
}
protected function getEntityManager()
{
return $this->getInjection('entityManager');
}
public function loadAdditionalFields(Entity $entity, $fieldList)
{
foreach ($entity->getRelationList() as $link) {
if ($entity->getRelationType($link) === 'belongsToParent') {
if (in_array($link, $fieldList)) {
$parent = $entity->get($link);
if ($parent instanceof Entity) {
$entity->set($link . 'Name', $parent->get('name'));
}
}
} else if ($entity->getRelationType($link) === 'belongsTo' && $entity->getRelationParam($link, 'noJoin') && $entity->hasField($link . 'Name')) {
if (in_array($link, $fieldList)) {
$related = $entity->get($link);
if ($related instanceof Entity) {
$entity->set($link . 'Name', $related->get('name'));
}
}
}
}
}
public function addAdditionalAttributes($entityType, &$attributeList, $fieldList)
{
$linkList = [];
if (!in_array('id', $attributeList)) {
$attributeList[] = 'id';
}
$linkDefs = $this->getMetadata()->get(['entityDefs', $entityType, 'links']);
if (is_array($linkDefs)) {
foreach ($linkDefs as $link => $defs) {
if (empty($defs['type'])) continue;
if ($defs['type'] === 'belongsToParent') {
$linkList[] = $link;
} else if ($defs['type'] === 'belongsTo' && !empty($defs['noJoin'])) {
if ($this->getMetadata()->get(['entityDefs', $entityType, 'fields', $link])) {
$linkList[] = $link;
}
}
}
}
foreach ($linkList as $item) {
if (in_array($item, $fieldList) && !in_array($item . 'Name', $attributeList)) {
$attributeList[] = $item . 'Name';
}
}
foreach ($fieldList as $field) {
$type = $this->getMetadata()->get(['entityDefs', $entityType, 'fields', $field, 'type']);
if ($type === 'currencyConverted') {
if (!in_array($field, $attributeList)) {
$attributeList[] = $field;
}
}
}
}
public function process($entityType, $params, $dataList)
{
if (!is_array($params['fieldList'])) {
throw new Error();
}
$phpExcel = new \PHPExcel();
$sheet = $phpExcel->setActiveSheetIndex(0);
if (isset($params['exportName'])) {
$exportName = $params['exportName'];
} else {
$exportName = $this->getInjection('language')->translate($entityType, 'scopeNamesPlural');
}
$sheetName = substr($exportName, 0, 30);
$badCharList = ['*', ':', '/', '\\', '?', '[', ']'];
foreach ($badCharList as $badChar) {
$sheetName = str_replace($badCharList, ' ', $sheetName);
}
$sheetName = str_replace('\'', '', $sheetName);
$sheet->setTitle($sheetName);
$fieldList = $params['fieldList'];
$titleStyle = array(
'font' => array(
'bold' => true,
'size' => 12
)
);
$dateStyle = array(
'font' => array(
'size' => 12
)
);
$sheet->setCellValue('A1', $exportName);
$sheet->setCellValue('B1', \PHPExcel_Shared_Date::PHPToExcel(strtotime(date('Y-m-d H:i:s'))));
$sheet->getStyle('A1')->applyFromArray($titleStyle);
$sheet->getStyle('B1')->applyFromArray($dateStyle);
$sheet->getStyle('B1')->getNumberFormat()
->setFormatCode($this->getInjection('dateTime')->getDateTimeFormat());
$azRange = range('A', 'Z');
$azRangeCopied = $azRange;
foreach ($azRangeCopied as $i => $char1) {
foreach ($azRangeCopied as $j => $char2) {
$azRange[] = $char1 . $char2;
if ($i * count($azRangeCopied) + $j === count($fieldList)) {
break 2;
}
}
}
$rowNumber = 3;
$linkColList = [];
$lastIndex = 0;
foreach ($fieldList as $i => $name) {
$col = $azRange[$i];
$defs = $this->getInjection('metadata')->get(['entityDefs', $entityType, 'fields', $name]);
if (!$defs) {
$defs['type'] = 'base';
}
$label = $name;
if (strpos($name, '_') !== false) {
list($linkName, $foreignField) = explode('_', $name);
$foreigScope = $this->getInjection('metadata')->get(['entityDefs', $entityType, 'links', $linkName, 'entity']);
if ($foreigScope) {
$label = $this->getInjection('language')->translate($linkName, 'links', $entityType) . '.' . $this->getInjection('language')->translate($foreignField, 'fields', $foreigScope);
}
} else {
$label = $this->getInjection('language')->translate($name, 'fields', $entityType);
}
$sheet->setCellValue($col . $rowNumber, $label);
$sheet->getColumnDimension($col)->setAutoSize(true);
if (
$defs['type'] == 'phone'
|| $defs['type'] == 'email'
|| $defs['type'] == 'url'
|| $defs['type'] == 'link'
|| $defs['type'] == 'linkParent'
) {
$linkColList[] = $col;
} else if ($name == 'name') {
$linkColList[] = $col;
}
$lastIndex = $i;
}
$col = $azRange[$i];
$headerStyle = array(
'font' => array(
'bold' => true,
'size' => 12
)
);
$sheet->getStyle("A$rowNumber:$col$rowNumber")->applyFromArray($headerStyle);
$sheet->setAutoFilter("A$rowNumber:$col$rowNumber");
$rowNumber++;
foreach ($dataList as $row) {
$i = 0;
foreach ($fieldList as $i => $name) {
$col = $azRange[$i];
$defs = $this->getInjection('metadata')->get(['entityDefs', $entityType, 'fields', $name]);
if (!$defs) {
$defs = array();
$defs['type'] = 'base';
}
$link = null;
if ($defs['type'] == 'link') {
if (array_key_exists($name.'Name', $row)) {
$sheet->setCellValue("$col$rowNumber", $row[$name.'Name']);
}
} else if ($defs['type'] == 'linkParent') {
if (array_key_exists($name.'Name', $row)) {
$sheet->setCellValue("$col$rowNumber", $row[$name.'Name']);
}
} else if ($defs['type'] == 'int') {
$sheet->setCellValue("$col$rowNumber", $row[$name] ?: 0);
} else if ($defs['type'] == 'currency') {
if (array_key_exists($name.'Currency', $row) && array_key_exists($name, $row)) {
$sheet->setCellValue("$col$rowNumber", $row[$name] ? $row[$name] : '');
$currency = $row[$name . 'Currency'];
$currencySymbol = $this->getMetadata()->get(['app', 'currency', 'symbolMap', $currency], '');
$sheet->getStyle("$col$rowNumber")
->getNumberFormat()
->setFormatCode('[$'.$currencySymbol.'-409]#,##0.00;-[$'.$currencySymbol.'-409]#,##0.00');
}
} else if ($defs['type'] == 'currencyConverted') {
if (array_key_exists($name, $row)) {
$currency = $this->getConfig()->get('baseCurrency');
$currencySymbol = $this->getMetadata()->get(['app', 'currency', 'symbolMap', $currency], '');
$sheet->getStyle("$col$rowNumber")
->getNumberFormat()
->setFormatCode('[$'.$currencySymbol.'-409]#,##0.00;-[$'.$currencySymbol.'-409]#,##0.00');
$sheet->setCellValue("$col$rowNumber", $row[$name] ? $row[$name] : '');
}
} else if ($defs['type'] == 'personName') {
if (!empty($row['name'])) {
$sheet->setCellValue("$col$rowNumber", $row['name']);
} else {
$personName = '';
if (!empty($row['firstName'])) {
$personName .= $row['firstName'];
}
if (!empty($row['lastName'])) {
if (!empty($row['firstName'])) {
$personName .= ' ';
}
$personName .= $row['lastName'];
}
$sheet->setCellValue("$col$rowNumber", $personName);
}
} else if ($defs['type'] == 'date') {
if (isset($row[$name])) {
$sheet->setCellValue("$col$rowNumber", \PHPExcel_Shared_Date::PHPToExcel(strtotime($row[$name])));
}
} else if ($defs['type'] == 'datetime' || $defs['type'] == 'datetimeOptional') {
if (isset($row[$name])) {
$sheet->setCellValue("$col$rowNumber", \PHPExcel_Shared_Date::PHPToExcel(strtotime($row[$name])));
}
} else if ($defs['type'] == 'image') {
if (isset($row[$name . 'Id']) && $row[$name . 'Id']) {
$attachment = $this->getEntityManager()->getEntity('Attachment', $row[$name . 'Id']);
if ($attachment) {
$objDrawing = new \PHPExcel_Worksheet_Drawing();
$filePath = $this->getInjection('fileStorageManager')->getLocalFilePath($attachment);
if ($filePath && file_exists($filePath)) {
$objDrawing->setPath($filePath);
$objDrawing->setHeight(100);
$objDrawing->setCoordinates("$col$rowNumber");
$objDrawing->setWorksheet($sheet);
$sheet->getRowDimension($rowNumber)->setRowHeight(100);
}
}
}
} else if ($defs['type'] == 'file') {
if (array_key_exists($name.'Name', $row)) {
$sheet->setCellValue("$col$rowNumber", $row[$name.'Name']);
}
} else if ($defs['type'] == 'enum') {
if (array_key_exists($name, $row)) {
$value = $this->getInjection('language')->translateOption($row[$name], $name, $entityType);
$sheet->setCellValue("$col$rowNumber", $value);
}
} else {
if (array_key_exists($name, $row)) {
$sheet->setCellValue("$col$rowNumber", $row[$name]);
}
}
$link = false;
if ($name == 'name') {
if (array_key_exists('id', $row)) {
$link = $this->getConfig()->getSiteUrl() . "/#".$entityType . "/view/" . $row['id'];
}
} else if ($defs['type'] == 'url') {
if (array_key_exists($name, $row) && filter_var($row[$name], FILTER_VALIDATE_URL)) {
$link = $row[$name];
}
} else if ($defs['type'] == 'link') {
if (array_key_exists($name.'Id', $row)) {
$foreignEntity = $this->getMetadata()->get(['entityDefs', $entityType, 'links', $name, 'entity']);
if ($foreignEntity) {
$link = $this->getConfig()->getSiteUrl() . "/#" . $foreignEntity. "/view/". $row[$name.'Id'];
}
}
} else if ($defs['type'] == 'file') {
if (array_key_exists($name.'Id', $row)) {
$link = $this->getConfig()->getSiteUrl() . "/?entryPoint=download&id=" . $row[$name.'Id'];
}
} else if ($defs['type'] == 'linkParent') {
if (array_key_exists($name.'Id', $row) && array_key_exists($name.'Type', $row)) {
$link = $this->getConfig()->getSiteUrl() . "/#".$row[$name.'Type']."/view/". $row[$name.'Id'];
}
} else if ($defs['type'] == 'phone') {
if (array_key_exists($name, $row)) {
$link = "tel:".$row[$name];
}
} else if ($defs['type'] == 'email' && array_key_exists($name, $row)) {
if (array_key_exists($name, $row)) {
$link = "mailto:".$row[$name];
}
}
if ($link) {
$sheet->getCell("$col$rowNumber")->getHyperlink()->setUrl($link);
$sheet->getCell("$col$rowNumber")->getHyperlink()->setTooltip($link);
}
}
$rowNumber++;
}
$startingRowNumber = 4;
foreach ($fieldList as $i => $name) {
$col = $azRange[$i];
$defs = $this->getInjection('metadata')->get(['entityDefs', $entityType, 'fields', $name]);
if (!$defs) {
$defs['type'] = 'base';
}
if ($col == 'A') {
$sheet->getStyle("A2:A$rowNumber")
->getNumberFormat()
->setFormatCode(\PHPExcel_Style_NumberFormat::FORMAT_TEXT);
} else {
switch($defs['type']) {
case 'currency':
case 'currencyConverted': {
} break;
case 'int': {
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
->getNumberFormat()
->setFormatCode('0');
} break;
case 'date': {
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
->getNumberFormat()
->setFormatCode($this->getInjection('dateTime')->getDateFormat());
} break;
case 'datetime': {
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
->getNumberFormat()
->setFormatCode($this->getInjection('dateTime')->getDateTimeFormat());
} break;
case 'datetimeOptional': {
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
->getNumberFormat()
->setFormatCode($this->getInjection('dateTime')->getDateTimeFormat());
} break;
default: {
$sheet->getStyle($col.$startingRowNumber.':'.$col.$rowNumber)
->getNumberFormat()
->setFormatCode('@');
} break;
}
}
}
$linkStyle = [
'font' => [
'color' => ['rgb' => '345b7c'],
'underline' => 'single'
]
];
foreach ($linkColList as $linkColumn) {
$sheet->getStyle($linkColumn.$startingRowNumber.':'.$linkColumn.$rowNumber)->applyFromArray($linkStyle);
}
$objWriter = \PHPExcel_IOFactory::createWriter($phpExcel, 'Excel2007');
if (!$this->getInjection('fileManager')->isDir('data/cache/')) {
$this->getInjection('fileManager')->mkdir('data/cache/');
}
$tempFileName = 'data/cache/' . 'export_' . substr(md5(rand()), 0, 7);
$objWriter->save($tempFileName);
$fp = fopen($tempFileName, 'r');
$xlsx = stream_get_contents($fp);
$this->getInjection('fileManager')->unlink($tempFileName);
return $xlsx;
}
}

View File

@@ -0,0 +1,115 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\FileStorage;
use \Espo\Entities\Attachment;
use \Espo\Core\Exceptions\Error;
class Manager
{
private $implementations = array();
private $implementationClassNameMap = array();
private $container;
public function __construct(array $implementationClassNameMap, $container)
{
$this->implementationClassNameMap = $implementationClassNameMap;
$this->container = $container;
}
private function getImplementation($storage = null)
{
if (!$storage) {
$storage = 'EspoUploadDir';
}
if (array_key_exists($storage, $this->implementations)) {
return $this->implementations[$storage];
}
if (!array_key_exists($storage, $this->implementationClassNameMap)) {
throw new Error("FileStorageManager: Unknown storage '{$storage}'");
}
$className = $this->implementationClassNameMap[$storage];
$implementation = new $className();
foreach ($implementation->getDependencyList() as $dependencyName) {
$implementation->inject($dependencyName, $this->container->get($dependencyName));
}
$this->implementations[$storage] = $implementation;
return $implementation;
}
public function isFile(Attachment $attachment)
{
$implementation = $this->getImplementation($attachment->get('storage'));
return $implementation->isFile($attachment);
}
public function getContents(Attachment $attachment)
{
$implementation = $this->getImplementation($attachment->get('storage'));
return $implementation->getContents($attachment);
}
public function putContents(Attachment $attachment, $contents)
{
$implementation = $this->getImplementation($attachment->get('storage'));
return $implementation->putContents($attachment, $contents);
}
public function unlink(Attachment $attachment)
{
$implementation = $this->getImplementation($attachment->get('storage'));
return $implementation->unlink($attachment);
}
public function getLocalFilePath(Attachment $attachment)
{
$implementation = $this->getImplementation($attachment->get('storage'));
return $implementation->getLocalFilePath($attachment);
}
public function hasDownloadUrl(Attachment $attachment)
{
$implementation = $this->getImplementation($attachment->get('storage'));
return $implementation->hasDownloadUrl($attachment);
}
public function getDownloadUrl(Attachment $attachment)
{
$implementation = $this->getImplementation($attachment->get('storage'));
return $implementation->getDownloadUrl($attachment);
}
}

View File

@@ -0,0 +1,89 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\FileStorage\Storages;
use \Espo\Core\Interfaces\Injectable;
abstract class Base implements Injectable
{
protected $dependencyList = [];
protected $injections = array();
public function inject($name, $object)
{
$this->injections[$name] = $object;
}
public function __construct()
{
$this->init();
}
protected function init()
{
}
protected function getInjection($name)
{
return $this->injections[$name];
}
protected function addDependency($name)
{
$this->dependencyList[] = $name;
}
protected function addDependencyList(array $list)
{
foreach ($list as $item) {
$this->addDependency($item);
}
}
public function getDependencyList()
{
return $this->dependencyList;
}
abstract public function hasDownloadUrl(\Espo\Entities\Attachment $attachment);
abstract public function getDownloadUrl(\Espo\Entities\Attachment $attachment);
abstract public function unlink(\Espo\Entities\Attachment $attachment);
abstract public function getContents(\Espo\Entities\Attachment $attachment);
abstract public function isFile(\Espo\Entities\Attachment $attachment);
abstract public function putContents(\Espo\Entities\Attachment $attachment, $contents);
abstract public function getLocalFilePath(\Espo\Entities\Attachment $attachment);
}

View File

@@ -0,0 +1,85 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\FileStorage\Storages;
use \Espo\Entities\Attachment;
use \Espo\Core\Exceptions\Error;
class EspoUploadDir extends Base
{
protected $dependencyList = ['fileManager'];
protected function getFileManager()
{
return $this->getInjection('fileManager');
}
public function unlink(Attachment $attachment)
{
return $this->getFileManager()->unlink($this->getFilePath($attachment));
}
public function isFile(Attachment $attachment)
{
return $this->getFileManager()->isFile($this->getFilePath($attachment));
}
public function getContents(Attachment $attachment)
{
return $this->getFileManager()->getContents($this->getFilePath($attachment));
}
public function putContents(Attachment $attachment, $contents)
{
return $this->getFileManager()->putContents($this->getFilePath($attachment), $contents);
}
public function getLocalFilePath(Attachment $attachment)
{
return $this->getFilePath($attachment);
}
protected function getFilePath(Attachment $attachment)
{
$sourceId = $attachment->getSourceId();
return 'data/upload/' . $sourceId;
}
public function getDownloadUrl(Attachment $attachment)
{
throw new Error();
}
public function hasDownloadUrl(Attachment $attachment)
{
return false;
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -65,6 +65,13 @@ class AttributeFetcher
$methodName = 'getFetched';
}
if ($entity->getAttributeParam($attribute, 'isParentName') && $methodName == 'get') {
$relationName = $entity->getAttributeParam($attribute, 'relation');
if ($parent = $entity->get($relationName)) {
return $parent->get('name');
}
}
return $entity->$methodName($attribute);
}

View File

@@ -0,0 +1,53 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\ArrayGroup;
use \Espo\Core\Exceptions\Error;
class IncludesType extends \Espo\Core\Formula\Functions\Base
{
public function process(\StdClass $item)
{
if (!property_exists($item, 'value') || !is_array($item->value)) {
throw new Error('Value for \'Array\\Includses\' item is not array.');
}
if (count($item->value) < 2) {
throw new Error('Bad arguments passed to \'Array\\Includses\'.');
}
$list = $this->evaluate($item->value[0]);
$needle = $this->evaluate($item->value[1]);
if (!is_array($list)) {
return false;
}
return in_array($needle, $list);
}
}

View File

@@ -0,0 +1,67 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\DateTimeGroup;
use \Espo\Core\Exceptions\Error;
class DateType extends \Espo\Core\Formula\Functions\Base
{
protected function init()
{
$this->addDependency('dateTime');
}
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
return true;
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 1) {
throw new Error();
}
$value = $this->evaluate($item->value[0]);
if (empty($value)) return 0;
if (strlen($value) > 11) {
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'D');
} else {
$resultString = $this->getInjection('dateTime')->convertSystemDate($value, 'D');
}
return intval($resultString);
}
}

View File

@@ -0,0 +1,72 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\DateTimeGroup;
use \Espo\Core\Exceptions\Error;
class DayOfWeekType extends \Espo\Core\Formula\Functions\Base
{
protected function init()
{
$this->addDependency('dateTime');
}
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
return true;
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 1) {
throw new Error();
}
$value = $this->evaluate($item->value[0]);
if (empty($value)) return 0;
if (strlen($value) > 11) {
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'D');
} else {
$resultString = $this->getInjection('dateTime')->convertSystemDate($value, 'D');
}
$result = intval($resultString) + 1;
if ($result == 8) {
$result = 1;
}
return $result;
}
}

View File

@@ -0,0 +1,132 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\DatetimeGroup;
use \Espo\Core\Exceptions\Error;
class DiffType extends \Espo\Core\Formula\Functions\Base
{
protected function init()
{
$this->addDependency('dateTime');
}
protected $intevalTypePropertyMap = array(
'years' => 'y', 'months' => 'm', 'days' => 'd', 'hours' => 'h', 'minutes' => 'i', 'seconds' => 's'
);
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
throw new Error();
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 2) {
throw new Error();
}
$dateTime1String = $this->evaluate($item->value[0]);
$dateTime2String = $this->evaluate($item->value[1]);
if (!$dateTime1String) {
return null;
}
if (!$dateTime2String) {
return null;
}
if (!is_string($dateTime1String)) {
throw new Error();
}
if (!is_string($dateTime2String)) {
throw new Error();
}
$intervalType = 'days';
if (count($item->value) > 2) {
$intervalType = $this->evaluate($item->value[2]);
}
if (!is_string($intervalType)) {
throw new Error();
}
if (!array_key_exists($intervalType, $this->intevalTypePropertyMap)) {
throw new Error('Not supported interval type' . $intervalType);
}
$isTime = false;
if (strlen($dateTime1String) > 10) {
$isTime = true;
}
try {
$dateTime1 = new \DateTime($dateTime1String);
$dateTime2 = new \DateTime($dateTime2String);
} catch (\Exception $e) {
return null;
}
$t1 = $dateTime1->getTimestamp();
$t2 = $dateTime2->getTimestamp();
$secondsDiff = $t1 - $t2;
if ($intervalType === 'seconds') {
$number = $secondsDiff;
} else if ($intervalType === 'minutes') {
$number = floor($secondsDiff / 60);
} else if ($intervalType === 'hours') {
$number = floor($secondsDiff / (60 * 60));
} else if ($intervalType === 'days') {
$number = floor($secondsDiff / (60 * 60 * 24));
} else {
$property = $this->intevalTypePropertyMap[$intervalType];
$interval = $dateTime2->diff($dateTime1);
$number = $interval->$property;
if ($interval->invert) {
$number *= -1;
}
if ($intervalType === 'months') {
$number += $interval->y * 12;
}
}
return $number;
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -58,10 +58,15 @@ class FormatType extends \Espo\Core\Formula\Functions\Base
}
$value = $this->evaluate($item->value[0]);
$format = null;
if (count($item->value) > 2) {
$format = $this->evaluate($item->value[2]);
}
if (strlen($value) > 11) {
return $this->getInjection('dateTime')->convertSystemDateTime($value, $timezone);
return $this->getInjection('dateTime')->convertSystemDateTime($value, $timezone, $format);
} else {
return $this->getInjection('dateTime')->convertSystemDate($value);
return $this->getInjection('dateTime')->convertSystemDate($value, $format);
}
}
}

View File

@@ -0,0 +1,67 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\DateTimeGroup;
use \Espo\Core\Exceptions\Error;
class HourType extends \Espo\Core\Formula\Functions\Base
{
protected function init()
{
$this->addDependency('dateTime');
}
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
return true;
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 1) {
throw new Error();
}
$value = $this->evaluate($item->value[0]);
if (empty($value)) return -1;
if (strlen($value) > 11) {
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'H');
} else {
return 0;
}
return intval($resultString);
}
}

View File

@@ -0,0 +1,67 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\DateTimeGroup;
use \Espo\Core\Exceptions\Error;
class MinuteType extends \Espo\Core\Formula\Functions\Base
{
protected function init()
{
$this->addDependency('dateTime');
}
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
return true;
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 1) {
throw new Error();
}
$value = $this->evaluate($item->value[0]);
if (empty($value)) return -1;
if (strlen($value) > 11) {
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'm');
} else {
return 0;
}
return intval($resultString);
}
}

View File

@@ -0,0 +1,67 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\DateTimeGroup;
use \Espo\Core\Exceptions\Error;
class MonthType extends \Espo\Core\Formula\Functions\Base
{
protected function init()
{
$this->addDependency('dateTime');
}
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
return true;
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 1) {
throw new Error();
}
$value = $this->evaluate($item->value[0]);
if (empty($value)) return 0;
if (strlen($value) > 11) {
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'M');
} else {
$resultString = $this->getInjection('dateTime')->convertSystemDate($value, 'M');
}
return intval($resultString);
}
}

View File

@@ -0,0 +1,67 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\DateTimeGroup;
use \Espo\Core\Exceptions\Error;
class YearType extends \Espo\Core\Formula\Functions\Base
{
protected function init()
{
$this->addDependency('dateTime');
}
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
return true;
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 1) {
throw new Error();
}
$value = $this->evaluate($item->value[0]);
if (empty($value)) return 0;
if (strlen($value) > 11) {
$resultString = $this->getInjection('dateTime')->convertSystemDateTime($value, null, 'YYYY');
} else {
$resultString = $this->getInjection('dateTime')->convertSystemDate($value, 'YYYY');
}
return intval($resultString);
}
}

View File

@@ -0,0 +1,54 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions;
use \Espo\ORM\Entity;
use \Espo\Core\Exceptions\Error;
class ListType extends Base
{
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
throw new Error();
}
if (!is_array($item->value)) {
throw new Error();
}
$result = [];
foreach ($item->value as $item) {
$result[] = $this->evaluate($item);
}
return $result;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\NumberGroup;
use \Espo\Core\Exceptions\Error;
class AbsType extends \Espo\Core\Formula\Functions\Base
{
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
return true;
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 1) {
throw new Error();
}
$value = $this->evaluate($item->value[0]);
if (!is_numeric($value)) {
return null;
}
return abs($value);
}
}

View File

@@ -0,0 +1,63 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Formula\Functions\NumberGroup;
use \Espo\Core\Exceptions\Error;
class RoundType extends \Espo\Core\Formula\Functions\Base
{
public function process(\StdClass $item)
{
if (!property_exists($item, 'value')) {
return true;
}
if (!is_array($item->value)) {
throw new Error();
}
if (count($item->value) < 1) {
throw new Error();
}
$value = $this->evaluate($item->value[0]);
$precision = 0;
if (count($item->value) > 1) {
$precision = $this->evaluate($item->value[1]);
}
if (!is_numeric($value)) {
return null;
}
return round($value, $precision);
}
}

View File

@@ -219,6 +219,11 @@ class Parser
$firstOperator = null;
$minIndex = null;
if ($expression === '') return (object) [
'type' => 'value',
'value' => null
];
foreach ($this->priorityList as $operationList) {
foreach ($operationList as $operator) {
$index = strpos($expression, $operator, 1);
@@ -229,7 +234,23 @@ class Parser
$possibleRightOperator = trim($operator . $expression[$index + 1]);
}
}
if ($possibleRightOperator && $possibleRightOperator != $operator && $this->operatorMap[$possibleRightOperator]) continue;
if (
$possibleRightOperator &&
$possibleRightOperator != $operator &&
!empty($this->operatorMap[$possibleRightOperator])
) continue;
$possibleLeftOperator = null;
if (strlen($operator) === 1) {
if ($index > 0) {
$possibleLeftOperator = trim($expression[$index - 1] . $operator);
}
}
if (
$possibleLeftOperator &&
$possibleLeftOperator != $operator &&
!empty($this->operatorMap[$possibleLeftOperator])
) continue;
$firstPart = substr($expression, 0, $index);
$secondPart = substr($expression, $index + strlen($operator));

View File

@@ -42,17 +42,14 @@ class HookManager
protected $cacheFile = 'data/cache/application/hooks.php';
/**
* List of defined hooks
* List of ignored hook methods
*
* @var array
*/
protected $hookList = array(
'beforeSave',
'afterSave',
'beforeRemove',
'afterRemove',
'afterRelate',
'afterUnrelate'
protected $ignoredMethodList = array(
'__construct',
'getDependencyList',
'inject'
);
protected $paths = array(
@@ -170,9 +167,12 @@ class HookManager
$hookFilePath = Util::concatPath($hookScopeDirPath, $hookFile);
$className = Util::getClassName($hookFilePath);
foreach($this->hookList as $hookName) {
$classMethods = get_class_methods($className);
$hookMethods = array_diff($classMethods, $this->ignoredMethodList);
foreach($hookMethods as $hookName) {
$entityHookData = isset($hookData[$scopeName][$hookName]) ? $hookData[$scopeName][$hookName] : array();
if (method_exists($className, $hookName) && !$this->isHookExists($className, $entityHookData)) {
if (!$this->isHookExists($className, $entityHookData)) {
$hookData[$normalizedScopeName][$hookName][$className::$order][] = $className;
}
}

View File

@@ -48,12 +48,15 @@ class Htmlizer
protected $acl;
public function __construct(FileManager $fileManager, DateTime $dateTime, NumberUtil $number, $acl = null)
protected $entityManager;
public function __construct(FileManager $fileManager, DateTime $dateTime, NumberUtil $number, $acl = null, $entityManager = null)
{
$this->fileManager = $fileManager;
$this->dateTime = $dateTime;
$this->number = $number;
$this->acl = $acl;
$this->entityManager = $entityManager;
}
protected function getAcl()
@@ -61,6 +64,11 @@ class Htmlizer
return $this->acl;
}
protected function getEntityManager()
{
return $this->entityManager;
}
protected function format($value)
{
if (is_float($value)) {
@@ -109,6 +117,9 @@ class Htmlizer
if ($item instanceof \StdClass) {
$v = get_object_vars($v);
}
if (!is_array($v)) {
$v = [];
}
foreach ($v as $k => $w) {
$v[$k] = $this->format($v[$k]);
}
@@ -163,7 +174,8 @@ class Htmlizer
'helpers' => [
'file' => function ($context, $options) {
if (count($context) && $context[0]) {
return 'data/upload/'.$context[0];
$id = $context[0];
return "?entryPoint=attachment&id=" . $id;
}
}
]
@@ -192,8 +204,20 @@ class Htmlizer
$html = $renderer($data);
$html = str_replace('?entryPoint=attachment&amp;', '?entryPoint=attachment&', $html);
$html = preg_replace('/\?entryPoint=attachment\&id=(.*)/', 'data/upload/$1', $html);
if ($this->getEntityManager()) {
$html = preg_replace_callback('/\?entryPoint=attachment\&id=([A-Za-z0-9]*)/', function ($matches) {
$id = $matches[1];
$attachment = $this->getEntityManager()->getEntity('Attachment', $id);
if ($attachment) {
$filePath = $this->getEntityManager()->getRepository('Attachment')->getFilePath($attachment);
return $filePath;
}
}, $html);
}
return $html;
}

View File

@@ -0,0 +1,74 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core;
abstract class Injectable implements \Espo\Core\Interfaces\Injectable
{
protected $dependencyList = array();
protected $injections = array();
public function inject($name, $object)
{
$this->injections[$name] = $object;
}
public function __construct()
{
$this->init();
}
protected function init()
{
}
protected function getInjection($name)
{
return $this->injections[$name];
}
protected function addDependency($name)
{
if (in_array($name, $this->dependencyList)) return;
$this->dependencyList[] = $name;
}
protected function addDependencyList(array $list)
{
foreach ($list as $item) {
$this->addDependency($item);
}
}
public function getDependencyList()
{
return $this->dependencyList;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core;
use \Espo\Core\Exceptions\Error;
class InjectableFactory
{
private $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function createByClassName($className)
{
if (class_exists($className)) {
$service = new $className();
if (!($service instanceof \Espo\Core\Interfaces\Injectable)) {
throw new Error("Class '$className' is not instance of Injectable interface");
}
$dependencyList = $service->getDependencyList();
foreach ($dependencyList as $name) {
$service->inject($name, $this->container->get($name));
}
return $service;
}
throw new Error("Class '$className' does not exist");
}
}

View File

@@ -104,12 +104,16 @@ class Importer
}
}
if ($parser->checkMessageAttribute($message, 'from')) {
$email->set('fromString', $parser->getMessageAttribute($message, 'from'));
$fromAddressData = $parser->getAddressDataFromMessage($message, 'from');
if ($fromAddressData) {
$fromString = ($fromAddressData['name'] ? ($fromAddressData['name'] . ' ') : '') . '<' . $fromAddressData['address'] .'>';
$email->set('fromString', $fromString);
}
if ($parser->checkMessageAttribute($message, 'reply-To')) {
$email->set('replyToString', $parser->getMessageAttribute($message, 'reply-To'));
$replyToData = $parser->getAddressDataFromMessage($message, 'reply-To');
if ($replyToData) {
$replyToString = ($replyToData['name'] ? ($replyToData['name'] . ' ') : '') . '<' . $replyToData['address'] .'>';
$email->set('replyToString', $replyToString);
}
$fromArr = $parser->getAddressListFromMessage($message, 'from');
@@ -124,6 +128,9 @@ class Importer
$email->set('cc', implode(';', $ccArr));
$email->set('replyTo', implode(';', $replyToArr));
$addressNameMap = $parser->getAddressNameMap($message);
$email->set('addressNameMap', $addressNameMap);
if ($folderData) {
foreach ($folderData as $uId => $folderId) {
$email->setLinkMultipleColumn('users', 'folderId', $uId, $folderId);

View File

@@ -0,0 +1,222 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Mail\Parsers;
class MailMimeParser
{
private $entityManager;
private $parser = array();
protected $messageHash = array();
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
protected function getEntityManager()
{
return $this->entityManager;
}
protected function getParser()
{
if (!$this->parser) {
$this->parser = new \ZBateson\MailMimeParser\MailMimeParser();
}
return $this->parser;
}
protected function loadContent($message)
{
$raw = $message->getFullRawContent();
$key = spl_object_hash($message);
$this->messageHash[$key] = $this->getParser()->parse($raw);
}
protected function getMessage($message)
{
$key = spl_object_hash($message);
if (!array_key_exists($key, $this->messageHash)) {
$raw = $message->getRawHeader();
if (!$raw) {
$raw = $message->getFullRawContent();
}
$this->messageHash[$key] = $this->getParser()->parse($raw);
}
return $this->messageHash[$key];
}
public function checkMessageAttribute($message, $attribute)
{
return $this->getMessage($message)->getHeaderValue($attribute) !== null;
}
public function getMessageAttribute($message, $attribute)
{
if (!$this->checkMessageAttribute($message, $attribute)) return null;
return $this->getMessage($message)->getHeaderValue($attribute);
}
public function getMessageMessageId($message)
{
return $this->getMessageAttribute($message, 'Message-ID');
}
public function getAddressNameMap($message)
{
$map = (object) [];
foreach (['from', 'to', 'cc', 'reply-To'] as $type) {
$header = $this->getMessage($message)->getHeader($type);
if ($header) {
$list = $header->getAddresses();
foreach ($list as $item) {
$address = $item->getEmail();
$name = $item->getName();
if ($name && $address) {
$map->$address = $name;
}
}
}
}
return $map;
}
public function getAddressDataFromMessage($message, $type)
{
$addressList = [];
$header = $this->getMessage($message)->getHeader($type);
if ($header) {
foreach ($header->getAddresses() as $item) {
return [
'address' => $item->getEmail(),
'name' => $item->getName()
];
}
}
return null;
}
public function getAddressListFromMessage($message, $type)
{
$addressList = [];
$header = $this->getMessage($message)->getHeader($type);
if ($header) {
$list = $header->getAddresses();
foreach ($list as $address) {
$addressList[] = $address->getEmail();
}
}
return $addressList;
}
public function fetchContentParts(\Espo\Entities\Email $email, $message)
{
$this->loadContent($message);
$bodyPlain = $this->getMessage($message)->getTextContent();
$bodyHtml = $this->getMessage($message)->getHtmlContent();
if ($bodyHtml) {
$email->set('isHtml', true);
$email->set('body', $bodyHtml);
$email->set('bodyPlain', $bodyPlain);
} else {
$email->set('isHtml', false);
$email->set('body', $bodyPlain);
}
if (!$email->get('body') && $email->get('bodyPlain')) {
$email->set('body', $email->get('bodyPlain'));
}
$attachmentObjList = $this->getMessage($message)->getAllAttachmentParts();
$inlineIds = array();
foreach ($attachmentObjList as $attachmentObj) {
$attachment = $this->getEntityManager()->getEntity('Attachment');
$content = $attachmentObj->getContent();
$disposition = $attachmentObj->getHeaderValue('Content-Disposition');
$attachment = $this->getEntityManager()->getEntity('Attachment');
$attachment->set('name', $attachmentObj->getHeaderParameter('Content-Disposition', 'filename', 'unnamed'));
$attachment->set('type', $attachmentObj->getHeaderValue('Content-Type'));
$contentId = $attachmentObj->getHeaderValue('Content-ID');
if ($contentId) {
$contentId = trim($contentId, '<>');
}
if ($disposition == 'inline') {
$attachment->set('role', 'Inline Attachment');
} else {
$attachment->set('role', 'Attachment');
}
$attachment->set('contents', $content);
$this->getEntityManager()->saveEntity($attachment);
if ($disposition == 'attachment') {
$email->addLinkMultipleId('attachments', $attachment->id);
if ($contentId) {
$inlineIds[$contentId] = $attachment->id;
}
} else if ($disposition == 'inline') {
if ($contentId) {
$inlineIds[$contentId] = $attachment->id;
}
}
}
$body = $email->get('body');
if (!empty($body)) {
foreach ($inlineIds as $cid => $attachmentId) {
if (strpos($body, 'cid:' . $cid) !== false) {
$body = str_replace('cid:' . $cid, '?entryPoint=attachment&amp;id=' . $attachmentId, $body);
} else {
$email->addLinkMultipleId('attachments', $attachmentId);
}
}
$email->set('body', $body);
}
}
}

View File

@@ -85,6 +85,42 @@ class PhpMimeMailParser
return $this->getMessageAttribute($message, 'Message-ID');
}
public function getAddressNameMap($message)
{
$map = (object) [];
foreach (['from', 'to', 'cc', 'reply-To'] as $type) {
if ($this->checkMessageAttribute($message, $type)) {
$list = $this->getParser($message)->getAddresses($type);
foreach ($list as $item) {
$name = $list[0]['display'];
$address = $list[0]['address'];
if ($name && $address && $name !== $address) {
$map->$address = $name;
}
}
}
}
return $map;
}
public function getAddressDataFromMessage($message, $type)
{
$addressList = [];
if ($this->checkMessageAttribute($message, $type)) {
$list = $this->getParser($message)->getAddresses($type);
if (count($list)) {
return [
'address' => $list[0]['address'],
'name' => $list[0]['display'],
];
}
}
return null;
}
public function getAddressListFromMessage($message, $type)
{
$addressList = [];
@@ -130,9 +166,10 @@ class PhpMimeMailParser
$attachment->set('name', $attachmentObj->getFileName());
$attachment->set('type', $attachmentObj->getContentType());
$contentId = $attachmentObj->getContentID();
if ($disposition == 'inline') {
$attachment->set('role', 'Inline Attachment');
$contentId = $attachmentObj->getContentID();
} else {
$attachment->set('role', 'Attachment');
}
@@ -142,11 +179,14 @@ class PhpMimeMailParser
$this->getEntityManager()->saveEntity($attachment);
if ($disposition == 'attachment') {
$attachmentsIds = $email->get('attachmentsIds');
$attachmentsIds[] = $attachment->id;
$email->set('attachmentsIds', $attachmentsIds);
$email->addLinkMultipleId('attachments', $attachment->id);
if ($contentId) {
$inlineIds[$contentId] = $attachment->id;
}
} else if ($disposition == 'inline') {
$inlineIds[$contentId] = $attachment->id;
if ($contentId) {
$inlineIds[$contentId] = $attachment->id;
}
}
}

View File

@@ -57,7 +57,9 @@ class Parser extends \PhpMimeMailParser\Parser
&& substr($part['content-type'], 0, 10) !== 'multipart/'
) {
// if we cannot get it by getMessageBody(), we assume it is an attachment
$disposition = 'attachment';
if ($disposition !== 'inline') {
$disposition = 'attachment';
}
}
if (in_array($disposition, $dispositions) === true && isset($filename) === true) {

View File

@@ -72,6 +72,45 @@ class ZendMail
return $messageId;
}
public function getAddressNameMap($message)
{
$map = (object) [];
$zendMessage = $message->getZendMessage();
foreach (['from', 'to', 'cc', 'reply-To'] as $type) {
if (isset($zendMessage->$type)) {
$list = $this->normilizeHeader($zendMessage->getHeader($type))->getAddressList();
foreach ($list as $item) {
$name = $item->getName();
$address = $item->getEmail();
if ($name && $address && $name !== $address) {
$map->$address = $name;
}
}
}
}
return $map;
}
public function getAddressDataFromMessage($message, $type)
{
$zendMessage = $message->getZendMessage();
$addressList = array();
if (isset($zendMessage->$type)) {
$list = $this->normilizeHeader($zendMessage->getHeader($type))->getAddressList();
foreach ($list as $address) {
return [
'address' => $address->getEmail(),
'name' => $address->getName()
];
}
}
return null;
}
public function getAddressListFromMessage($message, $type)
{
$zendMessage = $message->getZendMessage();
@@ -227,6 +266,13 @@ class ZendMail
$attachmentsIds = $email->get('attachmentsIds');
$attachmentsIds[] = $attachment->id;
$email->set('attachmentsIds', $attachmentsIds);
if (isset($part->contentID)) {
$contentId = trim($part->contentID, '<>');
if ($contentId) {
$inlineIds[$contentId] = $attachment->id;
}
}
} else if ($disposition == 'inline') {
$inlineIds[$contentId] = $attachment->id;
}

View File

@@ -189,6 +189,16 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterRemove', $entity, $options);
}
protected function afterMassRelate(Entity $entity, $relationName, array $params = array(), array $options = array())
{
$hookData = array(
'relationName' => $relationName,
'relationParams' => $params
);
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterMassRelate', $entity, $options, $hookData);
}
public function remove(Entity $entity, array $options = array())
{
$result = parent::remove($entity, $options);
@@ -269,18 +279,22 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
$entity->set('modifiedAt', $nowString);
}
if ($entity->hasAttribute('createdById')) {
if (empty($options['import']) || !$entity->has('createdById')) {
$entity->set('createdById', $this->getEntityManager()->getUser()->id);
if (empty($options['skipCreatedBy']) && (empty($options['import']) || !$entity->has('createdById'))) {
if ($this->getEntityManager()->getUser()) {
$entity->set('createdById', $this->getEntityManager()->getUser()->id);
}
}
}
} else {
if (empty($options['silent'])) {
if (empty($options['silent']) && empty($options['skipModifiedBy'])) {
if ($entity->hasAttribute('modifiedAt')) {
$entity->set('modifiedAt', $nowString);
}
if ($entity->hasAttribute('modifiedById')) {
$entity->set('modifiedById', $this->getEntityManager()->getUser()->id);
$entity->set('modifiedByName', $this->getEntityManager()->getUser()->get('name'));
if ($this->getEntityManager()->getUser()) {
$entity->set('modifiedById', $this->getEntityManager()->getUser()->id);
$entity->set('modifiedByName', $this->getEntityManager()->getUser()->get('name'));
}
}
}
}

View File

@@ -108,7 +108,7 @@ class AclManager extends \Espo\Core\AclManager
$config = $this->getContainer()->get('config');
$fileManager = $this->getContainer()->get('fileManager');
$metadata = $this->getContainer()->get('metadata');
$fieldManager = $this->getContainer()->get('fieldManager');
$fieldManager = $this->getContainer()->get('fieldManagerUtil');
$portal = $this->getPortal();
$this->tableHashMap[$key] = new $this->tableClassName($user, $portal, $config, $fileManager, $metadata, $fieldManager);
@@ -178,6 +178,15 @@ class AclManager extends \Espo\Core\AclManager
return parent::checkReadOnlyTeam($user, $scope);
}
public function checkReadNo(User $user, $scope)
{
if ($this->checkUserIsNotPortal($user)) {
$data = $this->getTable($user)->getScopeData($scope);
return $this->getMainManager()->checkReadNo($user, $data);
}
return parent::checkReadNo($user, $scope);
}
public function checkReadOnlyOwn(User $user, $scope)
{
if ($this->checkUserIsNotPortal($user)) {

View File

@@ -35,11 +35,6 @@ class Language extends \Espo\Core\Utils\Language
{
public function setPortal($portal)
{
if ($portal->get('language') !== '' && $portal->get('language')) {
if (!$this->getPreferences()->get('language')) {
$this->setLanguage($portal->get('language'));
}
}
}
}

View File

@@ -47,7 +47,7 @@ class ThemeManager extends \Espo\Core\Utils\ThemeManager
{
$theme = $this->portal->get('theme');
if (!$theme) {
$theme = $this->defaultName;
$theme = $this->config->get('theme', $this->defaultName);
}
return $theme;
}

View File

@@ -57,7 +57,9 @@ class Base
private $userTimeZone = null;
protected $additionalFilterTypeList = ['linkedWith', 'inCategory', 'isUserFromTeams'];
protected $additionalFilterTypeList = ['inCategory', 'isUserFromTeams'];
protected $textFilterUseContainsAttributeList = [];
const MIN_LENGTH_FOR_CONTENT_SEARCH = 4;
@@ -128,7 +130,7 @@ class Base
$result['orderBy'] = $sortBy;
$type = $this->getMetadata()->get(['entityDefs', $this->getEntityType(), 'fields', $sortBy, 'type']);
if ($type === 'link') {
if (in_array($type, ['link', 'file', 'image'])) {
$result['orderBy'] .= 'Name';
} else if ($type === 'linkParent') {
$result['orderBy'] .= 'Type';
@@ -144,7 +146,7 @@ class Base
$list = $this->getMetadata()->get(['entityDefs', $this->getEntityType(), 'fields', $sortBy, 'options']);
if ($list && is_array($list) && count($list)) {
if ($this->getMetadata()->get(['entityDefs', $this->getEntityType(), 'fields', $sortBy, 'isSorted'])) {
$list = asort($list);
asort($list);
}
if ($desc) {
$list = array_reverse($list);
@@ -210,7 +212,7 @@ class Base
foreach ($where as $item) {
$type = $item['type'];
if (!in_array($type, $ignoreTypeList)) {
$part = $this->getWherePart($item);
$part = $this->getWherePart($item, $result);
if (!empty($part)) {
$whereClause[] = $part;
}
@@ -257,13 +259,18 @@ class Base
$defs = $relDefs[$link];
if ($relationType == 'manyMany') {
$this->addJoin([$link, $link . 'Filter'], $result);
$this->addLeftJoin([$link, $link . 'Filter'], $result);
$midKeys = $seed->getRelationParam($link, 'midKeys');
if (!empty($midKeys)) {
$key = $midKeys[1];
$part[$link . 'Filter' . 'Middle.' . $key] = $idsValue;
}
} else if ($relationType == 'hasMany') {
$alias = $link . 'Filter';
$this->addLeftJoin([$link, $alias], $result);
$part[$alias . '.id'] = $idsValue;
} else if ($relationType == 'belongsTo') {
$key = $seed->getRelationParam($link, 'key');
if (!empty($key)) {
@@ -428,6 +435,8 @@ class Base
if (!$this->getUser()->isAdmin()) {
if ($this->getAcl()->checkReadOnlyTeam($this->getEntityType())) {
$this->accessOnlyTeam($result);
} else if ($this->getAcl()->checkReadNo($this->getEntityType())) {
$this->accessNo($result);
}
}
}
@@ -440,12 +449,21 @@ class Base
} else {
if ($this->getAcl()->checkReadOnlyContact($this->getEntityType())) {
$this->accessPortalOnlyContact($result);
} else if ($this->getAcl()->checkReadNo($this->getEntityType())) {
$this->accessNo($result);
}
}
}
}
}
protected function accessNo(&$result)
{
$result['whereClause'][] = array(
'id' => null
);
}
protected function accessOnlyOwn(&$result)
{
if ($this->hasAssignedUsersField()) {
@@ -724,7 +742,7 @@ class Base
$attribute = $w['attribute'];
}
if ($attribute) {
if (isset($w['type']) && $w['type'] === 'linkedWith') {
if (isset($w['type']) && in_array($w['type'], ['isLinked', 'isNotLinked', 'linkedWith', 'notLinkedWith', 'isUserFromTeams'])) {
if (in_array($attribute, $this->getAcl()->getScopeForbiddenFieldList($this->getEntityType()))) {
throw new Forbidden();
}
@@ -928,7 +946,7 @@ class Base
return $result;
}
protected function getWherePart($item)
protected function getWherePart($item, &$result = null)
{
$part = array();
@@ -940,30 +958,38 @@ class Base
$attribute = $item['attribute'];
}
if (!is_null($attribute) && !is_string($attribute)) {
throw new Error('Bad attribute in where statement');
}
if (!empty($attribute) && !empty($item['type'])) {
$methodName = 'getWherePart' . ucfirst($attribute) . ucfirst($item['type']);
if (method_exists($this, $methodName)) {
$value = null;
if (!empty($item['value'])) {
if (array_key_exists('value', $item)) {
$value = $item['value'];
}
return $this->$methodName($value);
return $this->$methodName($value, $result);
}
}
if (!empty($item['dateTime'])) {
return $this->convertDateTimeWhere($item);
}
if (!array_key_exists('value', $item)) {
$item['value'] = null;
}
if (!empty($item['type'])) {
switch ($item['type']) {
case 'or':
case 'and':
case 'not':
if (is_array($item['value'])) {
$arr = array();
foreach ($item['value'] as $i) {
$a = $this->getWherePart($i);
$a = $this->getWherePart($i, $result);
foreach ($a as $left => $right) {
if (!empty($right) || is_null($right) || $right === '') {
$arr[] = array($left => $right);
@@ -1107,7 +1133,7 @@ class Base
$quarter--;
if ($quarter == 0) {
$quarter = 4;
$dt->sub('P1Y');
$dt->modify('-1 year');
}
$part['AND'] = array(
$attribute . '>=' => $dt->add(new \DateInterval('P'.(($quarter - 1) * 3).'M'))->format('Y-m-d'),
@@ -1136,6 +1162,96 @@ class Base
);
}
break;
case 'isNotLinked':
if (!$result) break;
$alias = $attribute . 'IsNotLinkedFilter' . strval(rand(10000, 99999));;
$part[$alias . '.id'] = null;
$this->setDistinct(true, $result);
$this->addLeftJoin([$attribute, $alias], $result);
break;
case 'isLinked':
if (!$result) break;
$alias = $attribute . 'IsLinkedFilter' . strval(rand(10000, 99999));;
$part[$alias . '.id!='] = null;
$this->setDistinct(true, $result);
$this->addLeftJoin([$attribute, $alias], $result);
break;
case 'linkedWith':
$seed = $this->getSeed();
$link = $attribute;
if (!$seed->hasRelation($link)) break;
$alias = $link . 'Filter' . strval(rand(10000, 99999));
$value = $item['value'];
if (is_null($value)) break;
$relationType = $seed->getRelationType($link);
if ($relationType == 'manyMany') {
$this->addLeftJoin([$link, $alias], $result);
$midKeys = $seed->getRelationParam($link, 'midKeys');
if (!empty($midKeys)) {
$key = $midKeys[1];
$part[$alias . 'Middle.' . $key] = $value;
}
} else if ($relationType == 'hasMany') {
$this->addLeftJoin([$link, $alias], $result);
$part[$alias . '.id'] = $value;
} else if ($relationType == 'belongsTo') {
$key = $seed->getRelationParam($link, 'key');
if (!empty($key)) {
$part[$key] = $value;
}
} else if ($relationType == 'hasOne') {
$this->addLeftJoin([$link, $alias], $result);
$part[$alias . '.id'] = $value;
} else {
break;;
}
$this->setDistinct(true, $result);
break;
case 'notLinkedWith':
$seed = $this->getSeed();
$link = $attribute;
if (!$seed->hasRelation($link)) break;
$value = $item['value'];
if (is_null($value)) break;
$relationType = $seed->getRelationType($link);
$alias = $link . 'NotLinkedFilter' . strval(rand(10000, 99999));
if ($relationType == 'manyMany') {
$this->addLeftJoin([$link, $alias], $result);
$midKeys = $seed->getRelationParam($link, 'midKeys');
if (!empty($midKeys)) {
$key = $midKeys[1];
$result['joinConditions'][$alias] = [$key => $value];
$part[$alias . 'Middle.' . $key] = null;
}
} else if ($relationType == 'hasMany') {
$this->addLeftJoin([$link, $alias], $result);
$result['joinConditions'][$alias] = ['id' => $value];
$part[$alias . '.id'] = null;
} else if ($relationType == 'belongsTo') {
$key = $seed->getRelationParam($link, 'key');
if (!empty($key)) {
$part[$key . '!='] = $value;
}
} else if ($relationType == 'hasOne') {
$this->addLeftJoin([$link, alias], $result);
$part[$alias . '.id!='] = $value;
} else {
break;
}
$this->setDistinct(true, $result);
}
}
@@ -1322,6 +1438,9 @@ class Base
(
!empty($fieldDefs[$field]['type']) && $fieldDefs[$field]['type'] == 'text'
||
!empty($this->textFilterUseContainsAttributeList[$field])
||
!empty($fieldDefs[$field]['type']) && $fieldDefs[$field]['type'] == 'varchar' &&
$this->getConfig()->get('textFilterUseContainsForVarchar')
)
) {

View File

@@ -4,7 +4,7 @@
"tab": true,
"acl": true,
"aclPortal": true,
"aclPortalLevelList": ["all", "account", "own", "no"],
"aclPortalLevelList": ["all", "account", "contact", "own", "no"],
"customizable": true,
"importable": true,
"notifications": true

View File

@@ -4,7 +4,7 @@
"tab": true,
"acl": true,
"aclPortal": true,
"aclPortalLevelList": ["all", "account", "own", "no"],
"aclPortalLevelList": ["all", "account", "contact", "own", "no"],
"customizable": true,
"importable": true,
"notifications": true

View File

@@ -4,7 +4,7 @@
"tab": true,
"acl": true,
"aclPortal": true,
"aclPortalLevelList": ["all", "account", "own", "no"],
"aclPortalLevelList": ["all", "account", "contact", "own", "no"],
"customizable": true,
"importable": true,
"notifications": true

View File

@@ -1,6 +1,9 @@
{
"controller": "controllers/record",
"boolFilterList": ["onlyMy"],
"recordViews": {
"detail": "views/templates/event/record/detail"
},
"activityDefs": {
"activitiesCreate": true,
"historyCreate": true

View File

@@ -33,12 +33,12 @@
"options": [300, 600, 900, 1800, 2700, 3600, 7200],
"default": 300,
"notStorable": true,
"select": "TIMESTAMPDIFF(SECOND, date_start, date_end)",
"select": "TIMESTAMPDIFF(SECOND, {tableName}.date_start, {tableName}.date_end)",
"orderBy": "duration {direction}"
},
"parent": {
"type": "linkParent",
"entityList": ["Account", "Lead"]
"entityList": ["Account", "Lead", "Contact"]
},
"description": {
"type": "text"
@@ -46,7 +46,8 @@
"reminders": {
"type": "jsonArray",
"notStorable": true,
"view": "crm:views/meeting/fields/reminders"
"view": "crm:views/meeting/fields/reminders",
"layoutListDisabled": true
},
"createdAt": {
"type": "datetime",

View File

@@ -4,7 +4,7 @@
"tab": true,
"acl": true,
"aclPortal": true,
"aclPortalLevelList": ["all", "account", "own", "no"],
"aclPortalLevelList": ["all", "account", "contact", "own", "no"],
"customizable": true,
"importable": true,
"notifications": true

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create {entityType}": "Opret {entityTypeTranslated} "
}
}

View File

@@ -0,0 +1,10 @@
{
"links": {
"meetings": "Møder",
"calls": "Opkald",
"tasks": "Opgaver"
},
"labels": {
"Create {entityType}": "Opret {entityTypeTranslated} "
}
}

View File

@@ -0,0 +1,15 @@
{
"fields": {
"billingAddress": "Betalingsadresse",
"shippingAddress": "Leveringsadresse",
"website": "Website"
},
"links": {
"meetings": "Møder",
"calls": "Opkald",
"tasks": "Opgaver"
},
"labels": {
"Create {entityType}": "Opret {entityTypeTranslated} "
}
}

View File

@@ -0,0 +1,36 @@
{
"fields": {
"parent": "Henviser til",
"dateStart": "Startdato",
"dateEnd": "Slutdato",
"duration": "Varighed",
"status": "Status",
"reminders": "Underretninger"
},
"links": {
"parent": "Henviser til"
},
"options": {
"status": {
"Planned": "Planlagt",
"Held": "Gennemført",
"Not Held": "Ikke Gennemført"
}
},
"labels": {
"Create {entityType}": "Opret {entityTypeTranslated}",
"Schedule {entityType}": "Planlæg {entityTypeTranslated}",
"Log {entityType}": "Log {entityTypeTranslated}",
"Set Held": "Marker som Gennemført",
"Set Not Held": "Marker som Ikke Gennemført"
},
"massActions": {
"setHeld": "Marker som Gennemført",
"setNotHeld": "Marker som Ikke Gennemført"
},
"presetFilters": {
"planned": "Planlagt",
"held": "Gennemført",
"todays": "Dagens"
}
}

View File

@@ -0,0 +1,13 @@
{
"fields": {
"address": "Adresse"
},
"links": {
"meetings": "Møder",
"calls": "Opkald",
"tasks": "Opgaver"
},
"labels": {
"Create {entityType}": "Opret {entityTypeTranslated}"
}
}

View File

@@ -4,7 +4,8 @@
"dateStart": "Startdatum",
"dateEnd": "Enddatum",
"duration": "Dauer",
"status": "Status"
"status": "Status",
"reminders": "Erinnerungen"
},
"links": {
"parent": "Bezieht sich auf"

View File

@@ -1,5 +1,5 @@
{
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
}
}
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,10 @@
{
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
}
}
"links": {
"meetings": "Meetings",
"calls": "Calls",
"tasks": "Tasks"
},
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,15 @@
{
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
}
}
"fields": {
"billingAddress": "Billing Address",
"shippingAddress": "Shipping Address",
"website": "Website"
},
"links": {
"meetings": "Meetings",
"calls": "Calls",
"tasks": "Tasks"
},
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,36 @@
{
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
"fields": {
"parent": "Parent",
"dateStart": "Date de début",
"dateEnd": "Date End",
"duration": "Duration",
"status": "Status",
"reminders": "Reminders"
},
"links": {
"parent": "Parent"
},
"options": {
"status": {
"Planned": "Planned",
"Held": "Held",
"Not Held": "Not Held"
}
}
},
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}",
"Schedule {entityType}": "Schedule {entityTypeTranslated}",
"Log {entityType}": "Log {entityTypeTranslated}",
"Set Held": "Set Held",
"Set Not Held": "Set Not Held"
},
"massActions": {
"setHeld": "Set Held",
"setNotHeld": "Set Not Held"
},
"presetFilters": {
"planned": "Planned",
"held": "Held",
"todays": "Today's"
}
}

View File

@@ -1,5 +1,13 @@
{
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
}
}
"fields": {
"address": "Address"
},
"links": {
"meetings": "Meetings",
"calls": "Calls",
"tasks": "Tasks"
},
"labels": {
"Create {entityType}": "Créer un {entityTypeTranslated}"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create {entityType}": "Opprett {entityTypeTranslated}"
}
}

View File

@@ -0,0 +1,10 @@
{
"links": {
"meetings": "Møter",
"calls": "Samtaler",
"tasks": "Oppgaver"
},
"labels": {
"Create {entityType}": "Opprett {entityTypeTranslated}"
}
}

View File

@@ -0,0 +1,15 @@
{
"fields": {
"billingAddress": "Faktureringsadresse",
"shippingAddress": "Leveringsadresse",
"website": "Nettside"
},
"links": {
"meetings": "Møter",
"calls": "Samtaler",
"tasks": "Oppgaver"
},
"labels": {
"Create {entityType}": "Opprett {entityTypeTranslated}"
}
}

View File

@@ -0,0 +1,36 @@
{
"fields": {
"parent": "Forelder",
"dateStart": "Startdato",
"dateEnd": "Sluttdato",
"duration": "Varighet",
"status": "Status",
"reminders": "Påminnelser"
},
"links": {
"parent": "Forelder"
},
"options": {
"status": {
"Planned": "Planlagt",
"Held": "Gjennomført",
"Not Held": "Ikke gjennomført"
}
},
"labels": {
"Create {entityType}": "Opprett {entityTypeTranslated}",
"Schedule {entityType}": "Planlegg {entityTypeTranslated}",
"Log {entityType}": "Logg {entityTypeTranslated}",
"Set Held": "Merk som gjennomført",
"Set Not Held": "Merk som ikke gjennomført"
},
"massActions": {
"setHeld": "Merk som gjennomført",
"setNotHeld": "Merk som ikke gjennomført"
},
"presetFilters": {
"planned": "Planlagt",
"held": "Gjennomført",
"todays": "Dagens"
}
}

View File

@@ -0,0 +1,13 @@
{
"fields": {
"address": "Adresse"
},
"links": {
"meetings": "Møter",
"calls": "Samtaler",
"tasks": "Oppgaver"
},
"labels": {
"Create {entityType}": "Opprett {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,5 @@
{
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
}
}
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,10 @@
{
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
}
}
"links": {
"meetings": "Meetings",
"calls": "Calls",
"tasks": "Tasks"
},
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,15 @@
{
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
}
}
"fields": {
"billingAddress": "Платежный адрес",
"shippingAddress": "Адрес доставки",
"website": "Website"
},
"links": {
"meetings": "Meetings",
"calls": "Calls",
"tasks": "Tasks"
},
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,36 @@
{
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
"fields": {
"parent": "Parent",
"dateStart": "Date Start",
"dateEnd": "Date End",
"duration": "Duration",
"status": "Status",
"reminders": "Reminders"
},
"links": {
"parent": "Parent"
},
"options": {
"status": {
"Planned": "Planned",
"Held": "Held",
"Not Held": "Not Held"
}
}
},
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}",
"Schedule {entityType}": "Schedule {entityTypeTranslated}",
"Log {entityType}": "Log {entityTypeTranslated}",
"Set Held": "Set Held",
"Set Not Held": "Set Not Held"
},
"massActions": {
"setHeld": "Set Held",
"setNotHeld": "Set Not Held"
},
"presetFilters": {
"planned": "Запланировано",
"held": "Held",
"todays": "Сегодняшние"
}
}

View File

@@ -1,5 +1,13 @@
{
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
}
}
"fields": {
"address": "Адрес"
},
"links": {
"meetings": "Meetings",
"calls": "Calls",
"tasks": "Tasks"
},
"labels": {
"Create {entityType}": "Создать {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,5 @@
{
"labels": {
"Create {entityType}": "{entityTypeTranslated} Oluştur"
}
}
"labels": {
"Create {entityType}": "{entityTypeTranslated} oluştur"
}
}

View File

@@ -1,5 +1,10 @@
{
"labels": {
"Create {entityType}": "{entityTypeTranslated} Oluştur"
}
}
"links": {
"meetings": "Toplantılar",
"calls": "(Seslenme)",
"tasks": "Görevler"
},
"labels": {
"Create {entityType}": "{entityTypeTranslated} oluştur"
}
}

View File

@@ -1,5 +1,15 @@
{
"labels": {
"Create {entityType}": "{entityTypeTranslated} Oluştur"
}
}
"fields": {
"billingAddress": "Fatura Adresi",
"shippingAddress": "Teslimat Adresi",
"website": "Web sitesi "
},
"links": {
"meetings": "Toplantılar",
"calls": "(Seslenme)",
"tasks": "Görevler"
},
"labels": {
"Create {entityType}": "{entityTypeTranslated} oluştur"
}
}

View File

@@ -1,5 +1,36 @@
{
"labels": {
"Create {entityType}": "{entityTypeTranslated} Oluştur"
"fields": {
"parent": "Üst",
"dateStart": "Başlangıç Tarihi",
"dateEnd": "Son Tarih",
"duration": "Süre ",
"status": "Durum ",
"reminders": "Hatırlatıcılar"
},
"links": {
"parent": "Üst"
},
"options": {
"status": {
"Planned": "Planlandı",
"Held": "Düzenlenen",
"Not Held": "Düzenlenmedi"
}
}
},
"labels": {
"Create {entityType}": "{entityTypeTranslated} oluştur",
"Schedule {entityType}": "Zamanlama {entityTypeTranslated}",
"Log {entityType}": "{entityTypeTranslated} günlüğünü kaydet",
"Set Held": "Düzenlendi",
"Set Not Held": "Düzenlenmedi olarak ayarla"
},
"massActions": {
"setHeld": "Düzenlendi",
"setNotHeld": "Düzenlenmedi olarak ayarla"
},
"presetFilters": {
"planned": "Planlandı",
"held": "Düzenlenen",
"todays": "Bugünün"
}
}

View File

@@ -1,5 +1,13 @@
{
"labels": {
"Create {entityType}": "{entityTypeTranslated} Oluştur"
}
}
"fields": {
"address": "Adres "
},
"links": {
"meetings": "Toplantılar",
"calls": "(Seslenme)",
"tasks": "Görevler"
},
"labels": {
"Create {entityType}": "{entityTypeTranslated} oluştur"
}
}

View File

@@ -1,5 +1,5 @@
{
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
}
}
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,10 @@
{
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
}
}
"links": {
"meetings": "Зустрічі",
"calls": "Дзвінки",
"tasks": "Завдання"
},
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,15 @@
{
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
}
}
"fields": {
"billingAddress": "Адреса виставлення рахунку",
"shippingAddress": "Адреса доставки",
"website": "Вебсайт"
},
"links": {
"meetings": "Зустрічі",
"calls": "Дзвінки",
"tasks": "Завдання"
},
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
}
}

View File

@@ -1,5 +1,36 @@
{
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
"fields": {
"parent": "Батько",
"dateStart": "Дата початку",
"dateEnd": "Дата завершення",
"duration": "Тривалість",
"status": "Статус",
"reminders": "Нагадування"
},
"links": {
"parent": "Батько"
},
"options": {
"status": {
"Planned": "Плановий",
"Held": "Виконано",
"Not Held": "Не вміщений"
}
}
},
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}",
"Schedule {entityType}": "Розклад {entityTypeTranslated} ",
"Log {entityType}": "Лог {entityTypeTranslated}",
"Set Held": "Позначити виконаним",
"Set Not Held": "Позначити невиконаним"
},
"massActions": {
"setHeld": "Позначити виконаними",
"setNotHeld": "Позначити невиконаними"
},
"presetFilters": {
"planned": "Планований",
"held": "Виконані",
"todays": "Сьогоднішні"
}
}

View File

@@ -1,5 +1,13 @@
{
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
}
}
"fields": {
"address": "Адреса"
},
"links": {
"meetings": "Зустрічі",
"calls": "Дзвінки",
"tasks": "Завдання"
},
"labels": {
"Create {entityType}": "Створити {entityTypeTranslated}"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create {entityType}": "创建 {entityTypeTranslated}"
}
}

View File

@@ -0,0 +1,10 @@
{
"links": {
"meetings": "会晤",
"calls": "通话",
"tasks": "任务"
},
"labels": {
"Create {entityType}": "创建 {entityTypeTranslated}"
}
}

View File

@@ -0,0 +1,15 @@
{
"fields": {
"billingAddress": "账单地址",
"shippingAddress": "邮寄地址",
"website": "网站"
},
"links": {
"meetings": "会晤",
"calls": "通话",
"tasks": "任务"
},
"labels": {
"Create {entityType}": "创建 {entityTypeTranslated}"
}
}

View File

@@ -0,0 +1,36 @@
{
"fields": {
"parent": "关联",
"dateStart": "开始日期",
"dateEnd": "结束日期",
"duration": "持续时间",
"status": "状态",
"reminders": "提醒"
},
"links": {
"parent": "关联"
},
"options": {
"status": {
"Planned": "已计划",
"Held": "已举行",
"Not Held": "未举行"
}
},
"labels": {
"Create {entityType}": "创建 {entityTypeTranslated}",
"Schedule {entityType}": "计划 {entityTypeTranslated}",
"Log {entityType}": "记录 {entityTypeTranslated} ",
"Set Held": "设为已举行",
"Set Not Held": "设为未举行"
},
"massActions": {
"setHeld": "设为已举行",
"setNotHeld": "设为未举行"
},
"presetFilters": {
"planned": "已计划",
"held": "已举行",
"todays": "今天的"
}
}

View File

@@ -0,0 +1,13 @@
{
"fields": {
"address": "地址"
},
"links": {
"meetings": "会晤",
"calls": "通话",
"tasks": "任务"
},
"labels": {
"Create {entityType}": "创建 {entityTypeTranslated}"
}
}

View File

@@ -61,6 +61,13 @@ class Auth extends \Slim\Middleware
list($authUsername, $authPassword) = explode(':', base64_decode($espoAuth));
}
if (!isset($authUsername)) {
if (!empty($_COOKIE['auth-username']) && !empty($_COOKIE['auth-token'])) {
$authUsername = $_COOKIE['auth-username'];
$authPassword = $_COOKIE['auth-token'];
}
}
$espoCgiAuth = $req->headers('HTTP_ESPO_CGI_AUTH');
if (empty($espoCgiAuth)) {
$espoCgiAuth = $req->headers('REDIRECT_HTTP_ESPO_CGI_AUTH');

View File

@@ -31,6 +31,89 @@ namespace Espo\Core\Utils\Api;
class Slim extends \Slim\Slim
{
public function __construct(array $userSettings = array())
{
// Setup IoC container
$this->container = new \Slim\Helper\Set();
$this->container['settings'] = array_merge(static::getDefaultSettings(), $userSettings);
// Default environment
$this->container->singleton('environment', function ($c) {
/* ESPOCRM: change Environment class */
//return \Slim\Environment::getInstance();
return \Espo\Core\Utils\Api\Slim\Environment::getInstance();
/* ESPOCRM: end */
});
// Default request
$this->container->singleton('request', function ($c) {
return new \Slim\Http\Request($c['environment']);
});
// Default response
$this->container->singleton('response', function ($c) {
return new \Slim\Http\Response();
});
// Default router
$this->container->singleton('router', function ($c) {
return new \Slim\Router();
});
// Default view
$this->container->singleton('view', function ($c) {
$viewClass = $c['settings']['view'];
$templatesPath = $c['settings']['templates.path'];
$view = ($viewClass instanceOf \Slim\View) ? $viewClass : new $viewClass;
$view->setTemplatesDirectory($templatesPath);
return $view;
});
// Default log writer
$this->container->singleton('logWriter', function ($c) {
$logWriter = $c['settings']['log.writer'];
return is_object($logWriter) ? $logWriter : new \Slim\LogWriter($c['environment']['slim.errors']);
});
// Default log
$this->container->singleton('log', function ($c) {
$log = new \Slim\Log($c['logWriter']);
$log->setEnabled($c['settings']['log.enabled']);
$log->setLevel($c['settings']['log.level']);
$env = $c['environment'];
$env['slim.log'] = $log;
return $log;
});
// Default mode
$this->container['mode'] = function ($c) {
$mode = $c['settings']['mode'];
if (isset($_ENV['SLIM_MODE'])) {
$mode = $_ENV['SLIM_MODE'];
} else {
$envMode = getenv('SLIM_MODE');
if ($envMode !== false) {
$mode = $envMode;
}
}
return $mode;
};
// Define default middleware stack
$this->middleware = array($this);
$this->add(new \Slim\Middleware\Flash());
$this->add(new \Slim\Middleware\MethodOverride());
// Make default if first instance
if (is_null(static::getInstance())) {
$this->setName('default');
}
}
/**
* Redefine the run method

View File

@@ -0,0 +1,60 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Utils\Api\Slim;
class Environment extends \Slim\Environment
{
/**
* Define undefined $_SERVER variables
*/
private static function setUndefinedVariables()
{
$list = array(
'REQUEST_METHOD',
'REMOTE_ADDR',
'SERVER_NAME',
'SERVER_PORT',
'REQUEST_URI',
);
foreach ($list as $name) {
if (!array_key_exists($name, $_SERVER)) {
$_SERVER[$name] = '';
}
}
}
public static function getInstance($refresh = false)
{
static::setUndefinedVariables();
return parent::getInstance($refresh);
}
}

View File

@@ -109,6 +109,7 @@ class Auth
}
$user->set('isAdmin', $isAdmin);
$user->set('ipAddress', $_SERVER['REMOTE_ADDR']);
$entityManager->setUser($user);
$this->getContainer()->setUser($user);
@@ -116,7 +117,10 @@ class Auth
public function login($username, $password)
{
$authToken = $this->getEntityManager()->getRepository('AuthToken')->where(array('token' => $password))->findOne();
$authToken = $this->getEntityManager()->getRepository('AuthToken')->where(array(
'token' => $password,
'isActive' => true
))->findOne();
if ($authToken) {
if (!$this->allowAnyAccess) {
@@ -167,6 +171,8 @@ class Auth
$user->loadLinkMultipleField('teams');
}
$user->set('ipAddress', $_SERVER['REMOTE_ADDR']);
$this->getEntityManager()->setUser($user);
$this->getContainer()->setUser($user);
@@ -186,6 +192,7 @@ class Auth
$this->getEntityManager()->saveEntity($authToken);
$user->set('token', $authToken->get('token'));
$user->set('authTokenId', $authToken->id);
}
return true;
@@ -201,7 +208,8 @@ class Auth
{
$authToken = $this->getEntityManager()->getRepository('AuthToken')->where(array('token' => $token))->findOne();
if ($authToken) {
$this->getEntityManager()->removeEntity($authToken);
$authToken->set('isActive', false);
$this->getEntityManager()->saveEntity($authToken);
return true;
}
}

Some files were not shown because too many files have changed in this diff Show More