Moderate severityNVD Advisory· Published Aug 22, 2022· Updated Aug 3, 2024
Cross-site Scripting (XSS) - Stored in yetiforcecompany/yetiforcecrm
CVE-2022-2890
Description
Cross-site Scripting (XSS) - Stored in GitHub repository yetiforcecompany/yetiforcecrm prior to 6.4.0.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
yetiforce/yetiforce-crmPackagist | < 6.4.0 | 6.4.0 |
Affected products
1- Range: unspecified
Patches
12c14baaf8dbcYetiForce CRM ver. 6.4.0 (#16359)
300 files changed · +4014 −1453
api/doc/ManageConsents.json+4 −3 renamed@@ -32,6 +32,7 @@ "ApprovalsRegister" ], "summary": "Adds an consent entry", + "description": "Add record.", "operationId": "425399d47c958ba5c538827d258fde0a", "requestBody": { "description": "Required data for communication", @@ -95,6 +96,7 @@ "Approvals" ], "summary": "Gets the list of consents", + "description": "Gets consents.", "operationId": "04e7ebb08f943d466f20bb0e98311271", "parameters": [ { @@ -222,6 +224,7 @@ "BaseModule" ], "summary": "Gets the list of consents for specific entry", + "description": "Gets consents.", "operationId": "9fd993e544cb6935282883e505b8d1d6", "parameters": [ { @@ -295,6 +298,7 @@ "BaseModule" ], "summary": "Send e-mail", + "description": "Send e-mail.", "operationId": "86c8610aedbae9a8690ab71a3ae22134", "parameters": [ { @@ -563,7 +567,6 @@ }, "Exception": { "title": "General - Error exception", - "description": "Gets consents.", "properties": { "status": { "description": "0 - error", @@ -618,7 +621,6 @@ }, "BaseModule_Post_GetConsentsForEntry_Response": { "title": "Response body for GetConsentsForEntry", - "description": "Gets consents.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -667,7 +669,6 @@ }, "BaseModule_Post_SendEmail_Response": { "title": "Response body for SendEmail", - "description": "Send e-mail.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error",
api/doc/ManageConsents.yaml+4 −3 renamed@@ -24,6 +24,7 @@ paths: tags: - ApprovalsRegister summary: 'Adds an consent entry' + description: 'Add record.' operationId: 425399d47c958ba5c538827d258fde0a requestBody: description: 'Required data for communication' @@ -64,6 +65,7 @@ paths: tags: - Approvals summary: 'Gets the list of consents' + description: 'Gets consents.' operationId: 04e7ebb08f943d466f20bb0e98311271 parameters: - @@ -149,6 +151,7 @@ paths: tags: - BaseModule summary: 'Gets the list of consents for specific entry' + description: 'Gets consents.' operationId: 9fd993e544cb6935282883e505b8d1d6 parameters: - @@ -197,6 +200,7 @@ paths: tags: - BaseModule summary: 'Send e-mail' + description: 'Send e-mail.' operationId: 86c8610aedbae9a8690ab71a3ae22134 parameters: - @@ -317,7 +321,6 @@ components: type: object Exception: title: 'General - Error exception' - description: 'Gets consents.' properties: status: description: '0 - error' @@ -358,7 +361,6 @@ components: type: object BaseModule_Post_GetConsentsForEntry_Response: title: 'Response body for GetConsentsForEntry' - description: 'Gets consents.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -394,7 +396,6 @@ components: type: object BaseModule_Post_SendEmail_Response: title: 'Response body for SendEmail' - description: 'Send e-mail.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error'
api/doc/SMS.json+173 −0 added@@ -0,0 +1,173 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "YetiForce API for SMS. Type: SMS", + "description": "", + "termsOfService": "https://yetiforce.com/", + "contact": { + "name": "Devs API Team", + "url": "https://yetiforce.com/", + "email": "devs@yetiforce.com" + }, + "license": { + "name": "YetiForce Public License", + "url": "https://yetiforce.com/en/yetiforce/license" + }, + "version": "0.1" + }, + "servers": [ + { + "url": "https://gitdeveloper.yetiforce.com", + "description": "Demo server of the development version" + }, + { + "url": "https://gitstable.yetiforce.com", + "description": "Demo server of the latest stable version" + } + ], + "paths": { + "/webservice/SMS/SMSAPI/Reception": { + "get": { + "tags": [ + "SMSAPI" + ], + "summary": "Receipt of SMS", + "description": "Add record.", + "externalDocs": { + "description": "SMSApi Documentation", + "url": "https://www.smsapi.pl/docs" + }, + "operationId": "1d5b693764111be12b9441546ea6e2cb", + "responses": { + "200": { + "description": "Result", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SMS_SMSAPI_Post_Reception" + } + } + } + }, + "401": { + "description": "`No sent token` OR `Invalid token` OR `wrong data provided in the request`" + }, + "403": { + "description": "No permissions for module" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "ApiKeyAuth": [], + "token": [] + } + ] + } + }, + "/webservice/SMS/SMSAPI/Report": { + "get": { + "tags": [ + "SMSAPI" + ], + "summary": "Report for sms", + "description": "Update record status.", + "externalDocs": { + "description": "SMSApi Documentation", + "url": "https://www.smsapi.pl/docs" + }, + "operationId": "82162b057882b4798a1d4844f9e0161f", + "responses": { + "200": { + "description": "Result", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SMS_SMSAPI_Get_Report" + } + } + } + }, + "401": { + "description": "`No sent token` OR `Invalid token` OR `wrong data provided in the request`" + }, + "403": { + "description": "No permissions for module" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "ApiKeyAuth": [], + "token": [] + } + ] + }, + "post": { + "tags": [ + "SMSAPI" + ], + "summary": "Report for sms", + "description": "Update record status.", + "externalDocs": { + "description": "SMSApi Documentation", + "url": "https://www.smsapi.pl/docs" + }, + "operationId": "2d104552585271b46f199a9df6b49930", + "responses": { + "200": { + "description": "Result", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SMS_SMSAPI_Post_Report" + } + } + } + }, + "401": { + "description": "`No sent token` OR `Invalid token` OR `wrong data provided in the request`" + }, + "403": { + "description": "No permissions for module" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "ApiKeyAuth": [], + "token": [] + } + ] + } + } + }, + "components": { + "schemas": { + "SMS_SMSAPI_Post_Reception": { + "title": "Response", + "description": "Response", + "type": "string", + "example": "OK" + }, + "SMS_SMSAPI_Get_Report": { + "title": "Response", + "description": "Response", + "type": "string", + "example": "OK" + }, + "SMS_SMSAPI_Post_Report": { + "title": "Response", + "description": "Response", + "type": "string", + "example": "OK" + } + } + } +} \ No newline at end of file
api/doc/SMS.yaml+118 −0 added@@ -0,0 +1,118 @@ +openapi: 3.0.0 +info: + title: 'YetiForce API for SMS. Type: SMS' + description: '' + termsOfService: 'https://yetiforce.com/' + contact: + name: 'Devs API Team' + url: 'https://yetiforce.com/' + email: devs@yetiforce.com + license: + name: 'YetiForce Public License' + url: 'https://yetiforce.com/en/yetiforce/license' + version: '0.1' +servers: + - + url: 'https://gitdeveloper.yetiforce.com' + description: 'Demo server of the development version' + - + url: 'https://gitstable.yetiforce.com' + description: 'Demo server of the latest stable version' +paths: + /webservice/SMS/SMSAPI/Reception: + get: + tags: + - SMSAPI + summary: 'Receipt of SMS' + description: 'Add record.' + externalDocs: + description: 'SMSApi Documentation' + url: 'https://www.smsapi.pl/docs' + operationId: 1d5b693764111be12b9441546ea6e2cb + responses: + '200': + description: Result + content: + application/json: + schema: + $ref: '#/components/schemas/SMS_SMSAPI_Post_Reception' + '401': + description: '`No sent token` OR `Invalid token` OR `wrong data provided in the request`' + '403': + description: 'No permissions for module' + '405': + description: 'Method Not Allowed' + security: + - + ApiKeyAuth: [] + token: [] + /webservice/SMS/SMSAPI/Report: + get: + tags: + - SMSAPI + summary: 'Report for sms' + description: 'Update record status.' + externalDocs: + description: 'SMSApi Documentation' + url: 'https://www.smsapi.pl/docs' + operationId: 82162b057882b4798a1d4844f9e0161f + responses: + '200': + description: Result + content: + application/json: + schema: + $ref: '#/components/schemas/SMS_SMSAPI_Get_Report' + '401': + description: '`No sent token` OR `Invalid token` OR `wrong data provided in the request`' + '403': + description: 'No permissions for module' + '405': + description: 'Method Not Allowed' + security: + - + ApiKeyAuth: [] + token: [] + post: + tags: + - SMSAPI + summary: 'Report for sms' + description: 'Update record status.' + externalDocs: + description: 'SMSApi Documentation' + url: 'https://www.smsapi.pl/docs' + operationId: 2d104552585271b46f199a9df6b49930 + responses: + '200': + description: Result + content: + application/json: + schema: + $ref: '#/components/schemas/SMS_SMSAPI_Post_Report' + '401': + description: '`No sent token` OR `Invalid token` OR `wrong data provided in the request`' + '403': + description: 'No permissions for module' + '405': + description: 'Method Not Allowed' + security: + - + ApiKeyAuth: [] + token: [] +components: + schemas: + SMS_SMSAPI_Post_Reception: + title: Response + description: Response + type: string + example: OK + SMS_SMSAPI_Get_Report: + title: Response + description: Response + type: string + example: OK + SMS_SMSAPI_Post_Report: + title: Response + description: Response + type: string + example: OK
api/doc/WebservicePremium.json+71 −20 renamed@@ -1063,6 +1063,19 @@ }, "example": 5 }, + { + "name": "x-fields-params", + "in": "header", + "description": "JSON array - list of fields to be returned in the specified way", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Fields-Settings" + } + } + } + }, { "name": "x-header-fields", "in": "header", @@ -1201,6 +1214,21 @@ "$ref": "#/components/links/GetRecordById" } } + }, + "406": { + "description": "No input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + } + } } }, "security": [ @@ -1280,7 +1308,7 @@ "BaseModule" ], "summary": "Create record", - "description": "Gets data to save record", + "description": "Create new record", "operationId": "10503c8d531e680a764151718cb0ca34", "parameters": [ { @@ -1338,6 +1366,21 @@ "$ref": "#/components/links/GetRecordById" } } + }, + "406": { + "description": "No input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + } + } } }, "security": [ @@ -3979,7 +4022,6 @@ }, "BaseModule_Get_Dashboard_Response": { "title": "Base module - Dashboard response schema", - "description": "Get method - Gets widgets' data from the dashboard.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -4566,7 +4608,6 @@ }, "BaseModule_Get_Hierarchy_Response": { "title": "Base module - Hierarchy response schema", - "description": "Get method - Gets records hierarchy.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -4592,7 +4633,7 @@ }, "name": { "type": "string", - "example": "YetiForce Sp. z o.o." + "example": "YetiForce S.A." } }, "type": "object" @@ -4603,7 +4644,6 @@ }, "BaseModule_Get_Pdf_Response": { "title": "Base module - Generate PDF response schema", - "description": "Get method - Generates and downloads a PDF file from a template.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -4636,7 +4676,6 @@ }, "BaseModule_Get_PdfTemplates_Response": { "title": "Base module - Get PDF templates list response schema", - "description": "Get method - Gets a list of PDF templates.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -4678,7 +4717,6 @@ }, "BaseModule_Get_Privileges_Response": { "title": "Base module - Privileges response schema", - "description": "Get privileges for module.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -4703,9 +4741,18 @@ }, "type": "object" }, + "Fields-Settings": { + "title": "Custom field settings", + "description": "A list of custom parameters that can affect the return value of a given field.", + "type": "object", + "example": { + "password": { + "showHiddenData": true + } + } + }, "BaseModule_Get_Record_Response": { "title": "Base module - Response body for Record", - "description": "Get record detail.", "required": [ "status", "result" @@ -5666,7 +5713,6 @@ }, "BaseAction_SaveInventory_ResponseBodyError": { "title": "Base module - Create inventory record response error schema", - "description": "Put method - A store functionality - creates a record in an advanced module (orders).", "properties": { "errors": { "description": "Error details", @@ -5852,7 +5898,10 @@ }, "Products_Get_Record_Response": { "title": "Base module - Response body for Record", - "description": "{@inheritdoc}", + "required": [ + "status", + "result" + ], "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -5863,7 +5912,13 @@ ] }, "result": { - "description": "Record data", + "title": "Record data", + "required": [ + "name", + "id", + "fields", + "data" + ], "properties": { "name": { "description": "Record name", @@ -5893,7 +5948,11 @@ "$ref": "#/components/schemas/Record_Display_Details" }, "privileges": { - "description": "Parameters determining checking of editing rights and moving to the trash", + "title": "Parameters determining checking of editing rights and moving to the trash", + "required": [ + "isEditable", + "moveToTrash" + ], "properties": { "isEditable": { "description": "Check if record is editable", @@ -6004,7 +6063,6 @@ }, "Users_Get_AccessActivityHistory_Response": { "title": "Users module - History of access activity data", - "description": "Get user history of access activity.", "required": [ "status", "result" @@ -6071,7 +6129,6 @@ }, "Users_Put_ChangePassword_Response": { "title": "Users module - Users password change response body", - "description": "Put method.", "required": [ "status", "result" @@ -6447,7 +6504,6 @@ }, "Exception": { "title": "General - Error exception", - "description": "Post method.", "required": [ "status", "error" @@ -6534,7 +6590,6 @@ }, "Users_Put_Preferences_Response": { "title": "Users module - Response content of changing user settings", - "description": "Put method - Changes user’s preferences.", "required": [ "status", "result" @@ -6558,7 +6613,6 @@ }, "Users_Get_Record_Response": { "title": "Users module - Response body for user", - "description": "Get user detail.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -6692,7 +6746,6 @@ }, "Users_Post_ResetPassword_Response": { "title": "Users module - Users password reset response body", - "description": "Post method.", "required": [ "status", "result" @@ -6749,7 +6802,6 @@ }, "Users_Put_ResetPassword_Response": { "title": "Users module - Users password reset response body", - "description": "Put method.", "required": [ "status", "result" @@ -6773,7 +6825,6 @@ }, "Users_Get_TwoFactorAuth_Response": { "title": "Users module - Authentication secret details", - "description": "Get two factor authentication details.", "required": [ "status", "result"
api/doc/WebservicePremium.yaml+49 −20 renamed@@ -705,6 +705,15 @@ paths: schema: type: integer example: 5 + - + name: x-fields-params + in: header + description: 'JSON array - list of fields to be returned in the specified way' + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/Fields-Settings' - name: x-header-fields in: header @@ -797,6 +806,15 @@ paths: links: GetRecordById: $ref: '#/components/links/GetRecordById' + '406': + description: 'No input data' + content: + application/json: + schema: + $ref: '#/components/schemas/Exception' + application/xml: + schema: + $ref: '#/components/schemas/Exception' security: - basicAuth: [] @@ -851,7 +869,7 @@ paths: tags: - BaseModule summary: 'Create record' - description: 'Gets data to save record' + description: 'Create new record' operationId: 10503c8d531e680a764151718cb0ca34 parameters: - @@ -891,6 +909,15 @@ paths: links: GetRecordById: $ref: '#/components/links/GetRecordById' + '406': + description: 'No input data' + content: + application/json: + schema: + $ref: '#/components/schemas/Exception' + application/xml: + schema: + $ref: '#/components/schemas/Exception' security: - basicAuth: [] @@ -2657,7 +2684,6 @@ components: type: object BaseModule_Get_Dashboard_Response: title: 'Base module - Dashboard response schema' - description: 'Get method - Gets widgets'' data from the dashboard.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -2822,7 +2848,6 @@ components: type: object BaseModule_Get_Hierarchy_Response: title: 'Base module - Hierarchy response schema' - description: 'Get method - Gets records hierarchy.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -2844,12 +2869,11 @@ components: example: 0 name: type: string - example: 'YetiForce Sp. z o.o.' + example: 'YetiForce S.A.' type: object type: object BaseModule_Get_Pdf_Response: title: 'Base module - Generate PDF response schema' - description: 'Get method - Generates and downloads a PDF file from a template.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -2873,7 +2897,6 @@ components: type: object BaseModule_Get_PdfTemplates_Response: title: 'Base module - Get PDF templates list response schema' - description: 'Get method - Gets a list of PDF templates.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -2904,7 +2927,6 @@ components: type: object BaseModule_Get_Privileges_Response: title: 'Base module - Privileges response schema' - description: 'Get privileges for module.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -2922,9 +2944,15 @@ components: title: Action type: boolean type: object + Fields-Settings: + title: 'Custom field settings' + description: 'A list of custom parameters that can affect the return value of a given field.' + type: object + example: + password: + showHiddenData: true BaseModule_Get_Record_Response: title: 'Base module - Response body for Record' - description: 'Get record detail.' required: - status - result @@ -3383,7 +3411,6 @@ components: type: object BaseAction_SaveInventory_ResponseBodyError: title: 'Base module - Create inventory record response error schema' - description: 'Put method - A store functionality - creates a record in an advanced module (orders).' properties: errors: description: 'Error details' @@ -3525,7 +3552,9 @@ components: type: object Products_Get_Record_Response: title: 'Base module - Response body for Record' - description: '{@inheritdoc}' + required: + - status + - result properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -3534,7 +3563,12 @@ components: - 0 - 1 result: - description: 'Record data' + title: 'Record data' + required: + - name + - id + - fields + - data properties: name: description: 'Record name' @@ -3558,7 +3592,10 @@ components: data: $ref: '#/components/schemas/Record_Display_Details' privileges: - description: 'Parameters determining checking of editing rights and moving to the trash' + title: 'Parameters determining checking of editing rights and moving to the trash' + required: + - isEditable + - moveToTrash properties: isEditable: description: 'Check if record is editable' @@ -3635,7 +3672,6 @@ components: type: object Users_Get_AccessActivityHistory_Response: title: 'Users module - History of access activity data' - description: 'Get user history of access activity.' required: - status - result @@ -3685,7 +3721,6 @@ components: type: object Users_Put_ChangePassword_Response: title: 'Users module - Users password change response body' - description: 'Put method.' required: - status - result @@ -3971,7 +4006,6 @@ components: type: object Exception: title: 'General - Error exception' - description: 'Post method.' required: - status - error @@ -4036,7 +4070,6 @@ components: menuPin: 1 Users_Put_Preferences_Response: title: 'Users module - Response content of changing user settings' - description: 'Put method - Changes user’s preferences.' required: - status - result @@ -4054,7 +4087,6 @@ components: type: object Users_Get_Record_Response: title: 'Users module - Response body for user' - description: 'Get user detail.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -4153,7 +4185,6 @@ components: type: object Users_Post_ResetPassword_Response: title: 'Users module - Users password reset response body' - description: 'Post method.' required: - status - result @@ -4195,7 +4226,6 @@ components: type: object Users_Put_ResetPassword_Response: title: 'Users module - Users password reset response body' - description: 'Put method.' required: - status - result @@ -4213,7 +4243,6 @@ components: type: object Users_Get_TwoFactorAuth_Response: title: 'Users module - Authentication secret details' - description: 'Get two factor authentication details.' required: - status - result
api/doc/WebserviceStandard.json+201 −15 renamed@@ -604,6 +604,19 @@ "type": "integer" }, "example": 5 + }, + { + "name": "x-fields-params", + "in": "header", + "description": "JSON array - list of fields to be returned in the specified way", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Fields-Settings" + } + } + } } ], "responses": { @@ -734,6 +747,21 @@ "$ref": "#/components/links/GetRecordById" } } + }, + "406": { + "description": "No input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + } + } } }, "security": [ @@ -813,7 +841,7 @@ "BaseModule" ], "summary": "Create record", - "description": "Gets data to save record", + "description": "Create new record", "operationId": "ea3b9bea091cbde741323b5393901825", "parameters": [ { @@ -871,6 +899,21 @@ "$ref": "#/components/links/GetRecordById" } } + }, + "406": { + "description": "No input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + } + } } }, "security": [ @@ -1901,7 +1944,7 @@ ], "summary": "Data for the user", "description": "Gets details about the user", - "operationId": "5de1069868c749968f98e50485b6f084", + "operationId": "getUser", "parameters": [ { "name": "userId", @@ -1992,6 +2035,86 @@ ] } }, + "/webservice/WebserviceStandard/Users/Record": { + "post": { + "tags": [ + "Users" + ], + "summary": "Create user", + "description": "Create new user", + "operationId": "b2550c068a0148252c584ed08f9d7fae", + "parameters": [ + { + "name": "X-ENCRYPTED", + "in": "header", + "required": true, + "schema": { + "$ref": "#/components/schemas/Header-Encrypted" + } + } + ], + "requestBody": { + "description": "Contents of the request contains an associative array with the user data.", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User_Create_Details" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User_Create_Details" + } + } + } + }, + "responses": { + "200": { + "description": "Contents of the response contains only id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User_Post_Record_Response" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User_Post_Record_Response" + } + } + }, + "links": { + "GetUserById": { + "$ref": "#/components/links/GetUserById" + } + } + }, + "406": { + "description": "No input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Exception" + } + } + } + } + }, + "security": [ + { + "basicAuth": [], + "ApiKeyAuth": [], + "token": [] + } + ] + } + }, "/webservice/WebserviceStandard/Users/RecordsList": { "get": { "tags": [ @@ -3282,7 +3405,6 @@ }, "BaseModule_Privileges_ResponseBody": { "title": "Base module - Privileges response schema", - "description": "Get privileges for module.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -3309,9 +3431,18 @@ }, "type": "object" }, + "Fields-Settings": { + "title": "Custom field settings", + "description": "A list of custom parameters that can affect the return value of a given field.", + "type": "object", + "example": { + "password": { + "showHiddenData": true + } + } + }, "BaseModule_Get_Record_Response": { "title": "Base module - Response body for Record", - "description": "Get record detail.", "required": [ "status", "result" @@ -4055,7 +4186,6 @@ }, "Users_Get_AccessActivityHistory_Response": { "title": "Users module - History of access activity data", - "description": "Get user history of access activity.", "required": [ "status", "result" @@ -4122,7 +4252,6 @@ }, "Users_Put_ChangePassword_Response": { "title": "Users module - Users password change response body", - "description": "Put method.", "required": [ "status", "result" @@ -4428,7 +4557,6 @@ }, "Exception": { "title": "General - Error exception", - "description": "Post method.", "required": [ "status", "error" @@ -4508,7 +4636,6 @@ }, "Users_Get_Record_Response": { "title": "Users module - Response body for user", - "description": "Get user detail.", "properties": { "status": { "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", @@ -4573,6 +4700,65 @@ }, "type": "object" }, + "User_Post_Record_Response": { + "title": "User - Created user", + "description": "Contents of the response contains only id and name", + "required": [ + "status", + "result" + ], + "properties": { + "status": { + "description": "A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error", + "type": "integer", + "enum": [ + 0, + 1 + ] + }, + "result": { + "title": "User data", + "description": "Created user id and name.", + "required": [ + "id", + "name" + ], + "properties": { + "id": { + "description": "Id of the newly created user", + "type": "integer", + "example": 22 + }, + "name": { + "description": "Id of the newly created user", + "type": "string", + "example": "YetiForce Name" + }, + "skippedData": { + "description": "List of parameters passed in the request that were skipped in the write process", + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "User_Create_Details": { + "title": "General - User create details", + "description": "User data in user format for create view", + "type": "object", + "example": { + "user_name": "tom", + "first_name": "Tom", + "last_name": "Kowalski", + "roleid": "H38", + "password": "MyFunP@ssword", + "confirm_password": "MyFunP@ssword", + "email1": "my@email.com", + "language": "en-US" + } + }, "Users_RecordsList_ResponseBody": { "title": "Users module - Response action users list", "description": "Module action record list response body", @@ -4636,7 +4822,6 @@ }, "Users_Post_ResetPassword_Response": { "title": "Users module - Users password reset response body", - "description": "Post method.", "required": [ "status", "result" @@ -4687,7 +4872,6 @@ }, "Users_Put_ResetPassword_Response": { "title": "Users module - Users password reset response body", - "description": "Put method.", "required": [ "status", "result" @@ -4711,7 +4895,6 @@ }, "Users_Get_TwoFactorAuth_Response": { "title": "Users module - Authentication secret details", - "description": "Get two factor authentication details.", "required": [ "status", "result" @@ -4811,6 +4994,13 @@ "recordId": "$response.body#/result/id" }, "description": "The `id` value returned in the response can be used as the `recordId` parameter in `GET /webservice/{moduleName}/Record/{recordId}`." + }, + "GetUserById": { + "operationId": "getUser", + "parameters": { + "recordId": "$response.body#/result/id" + }, + "description": "The `id` value returned in the response can be used as the `userId` parameter in `GET /webservice/Users/Record/{userId}`." } } }, @@ -4823,10 +5013,6 @@ "name": "BaseAction", "description": "Access to user methods" }, - { - "name": "Products", - "description": "Products methods" - }, { "name": "Users", "description": "Access to user methods"
api/doc/WebserviceStandard.yaml+138 −14 renamed@@ -401,6 +401,15 @@ paths: schema: type: integer example: 5 + - + name: x-fields-params + in: header + description: 'JSON array - list of fields to be returned in the specified way' + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/Fields-Settings' responses: '200': description: 'Gets data for the record' @@ -486,6 +495,15 @@ paths: links: GetRecordById: $ref: '#/components/links/GetRecordById' + '406': + description: 'No input data' + content: + application/json: + schema: + $ref: '#/components/schemas/Exception' + application/xml: + schema: + $ref: '#/components/schemas/Exception' security: - basicAuth: [] @@ -540,7 +558,7 @@ paths: tags: - BaseModule summary: 'Create record' - description: 'Gets data to save record' + description: 'Create new record' operationId: ea3b9bea091cbde741323b5393901825 parameters: - @@ -580,6 +598,15 @@ paths: links: GetRecordById: $ref: '#/components/links/GetRecordById' + '406': + description: 'No input data' + content: + application/json: + schema: + $ref: '#/components/schemas/Exception' + application/xml: + schema: + $ref: '#/components/schemas/Exception' security: - basicAuth: [] @@ -1280,7 +1307,7 @@ paths: - Users summary: 'Data for the user' description: 'Gets details about the user' - operationId: 5de1069868c749968f98e50485b6f084 + operationId: getUser parameters: - name: userId @@ -1340,6 +1367,57 @@ paths: basicAuth: [] ApiKeyAuth: [] token: [] + /webservice/WebserviceStandard/Users/Record: + post: + tags: + - Users + summary: 'Create user' + description: 'Create new user' + operationId: b2550c068a0148252c584ed08f9d7fae + parameters: + - + name: X-ENCRYPTED + in: header + required: true + schema: + $ref: '#/components/schemas/Header-Encrypted' + requestBody: + description: 'Contents of the request contains an associative array with the user data.' + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/User_Create_Details' + application/xml: + schema: + $ref: '#/components/schemas/User_Create_Details' + responses: + '200': + description: 'Contents of the response contains only id' + content: + application/json: + schema: + $ref: '#/components/schemas/User_Post_Record_Response' + application/xml: + schema: + $ref: '#/components/schemas/User_Post_Record_Response' + links: + GetUserById: + $ref: '#/components/links/GetUserById' + '406': + description: 'No input data' + content: + application/json: + schema: + $ref: '#/components/schemas/Exception' + application/xml: + schema: + $ref: '#/components/schemas/Exception' + security: + - + basicAuth: [] + ApiKeyAuth: [] + token: [] /webservice/WebserviceStandard/Users/RecordsList: get: tags: @@ -1988,7 +2066,6 @@ components: type: object BaseModule_Privileges_ResponseBody: title: 'Base module - Privileges response schema' - description: 'Get privileges for module.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -2008,9 +2085,15 @@ components: description: Action type: boolean type: object + Fields-Settings: + title: 'Custom field settings' + description: 'A list of custom parameters that can affect the return value of a given field.' + type: object + example: + password: + showHiddenData: true BaseModule_Get_Record_Response: title: 'Base module - Response body for Record' - description: 'Get record detail.' required: - status - result @@ -2424,7 +2507,6 @@ components: type: object Users_Get_AccessActivityHistory_Response: title: 'Users module - History of access activity data' - description: 'Get user history of access activity.' required: - status - result @@ -2474,7 +2556,6 @@ components: type: object Users_Put_ChangePassword_Response: title: 'Users module - Users password change response body' - description: 'Put method.' required: - status - result @@ -2708,7 +2789,6 @@ components: type: object Exception: title: 'General - Error exception' - description: 'Post method.' required: - status - error @@ -2768,7 +2848,6 @@ components: type: object Users_Get_Record_Response: title: 'Users module - Response body for user' - description: 'Get user detail.' properties: status: description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' @@ -2816,6 +2895,52 @@ components: type: object type: object type: object + User_Post_Record_Response: + title: 'User - Created user' + description: 'Contents of the response contains only id and name' + required: + - status + - result + properties: + status: + description: 'A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error' + type: integer + enum: + - 0 + - 1 + result: + title: 'User data' + description: 'Created user id and name.' + required: + - id + - name + properties: + id: + description: 'Id of the newly created user' + type: integer + example: 22 + name: + description: 'Id of the newly created user' + type: string + example: 'YetiForce Name' + skippedData: + description: 'List of parameters passed in the request that were skipped in the write process' + type: object + type: object + type: object + User_Create_Details: + title: 'General - User create details' + description: 'User data in user format for create view' + type: object + example: + user_name: tom + first_name: Tom + last_name: Kowalski + roleid: H38 + password: MyFunP@ssword + confirm_password: MyFunP@ssword + email1: my@email.com + language: en-US Users_RecordsList_ResponseBody: title: 'Users module - Response action users list' description: 'Module action record list response body' @@ -2862,7 +2987,6 @@ components: type: object Users_Post_ResetPassword_Response: title: 'Users module - Users password reset response body' - description: 'Post method.' required: - status - result @@ -2899,7 +3023,6 @@ components: type: object Users_Put_ResetPassword_Response: title: 'Users module - Users password reset response body' - description: 'Put method.' required: - status - result @@ -2917,7 +3040,6 @@ components: type: object Users_Get_TwoFactorAuth_Response: title: 'Users module - Authentication secret details' - description: 'Get two factor authentication details.' required: - status - result @@ -2991,16 +3113,18 @@ components: parameters: recordId: '$response.body#/result/id' description: 'The `id` value returned in the response can be used as the `recordId` parameter in `GET /webservice/{moduleName}/Record/{recordId}`.' + GetUserById: + operationId: getUser + parameters: + recordId: '$response.body#/result/id' + description: 'The `id` value returned in the response can be used as the `userId` parameter in `GET /webservice/Users/Record/{userId}`.' tags: - name: BaseModule description: 'Access to record methods' - name: BaseAction description: 'Access to user methods' - - - name: Products - description: 'Products methods' - name: Users description: 'Access to user methods'
api/webservice/Controller.php+10 −12 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -84,22 +84,20 @@ public function preProcess(): bool $this->response->setAcceptableMethods($handler->allowedMethod); return false; } - $this->app = Core\Auth::init($this); - $this->app['tables'] = Core\Containers::$listTables[$this->app['type']] ?? []; - if ($this->app['type'] !== $this->request->getByType('_container', 'Alnum')) { - throw new Core\Exception('Invalid api type', 404); - } + $this->headers = $this->request->getHeaders(); + Core\Auth::init($this); + if (empty($this->app)) { + throw new Core\Exception('Web service - Applications: Unauthorized', 401); + } + $this->app['tables'] = Core\Containers::$listTables[$this->app['type']] ?? []; if (!empty($this->app['ips']) && !\in_array(\App\RequestUtil::getRemoteIP(true), array_map('trim', explode(',', $this->app['ips'])))) { throw new Core\Exception('Illegal IP address', 401); } - if ($this->headers['x-api-key'] !== \App\Encryption::getInstance()->decrypt($this->app['api_key'])) { - throw new Core\Exception('Invalid api key', 401); - } - if (empty($this->request->getByType('action', 'Alnum'))) { + if ($this->request->isEmpty('action', true)) { throw new Core\Exception('No action', 404); } - \App\Process::$processName = $this->request->getByType('action', 'Alnum'); + \App\Process::$processName = $this->request->getByType('action', \App\Purifier::ALNUM); \App\Process::$processType = $this->app['type']; return true; }
api/webservice/Core/Auth/AbstractAuth.php+6 −11 modified@@ -4,9 +4,10 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace Api\Core\Auth; @@ -16,9 +17,6 @@ */ abstract class AbstractAuth { - /** @var array Current server details (w_#__servers) */ - protected $currentServer; - /** @var \Api\Controller Controller instance */ protected $api; @@ -46,12 +44,9 @@ public function setApi(\Api\Controller $api): void abstract protected function authenticate(string $realm): bool; /** - * Get current server details. + * Set server data. * - * @return array + * @return self */ - public function getCurrentServer(): array - { - return $this->currentServer; - } + abstract protected function setServer(): self; }
api/webservice/Core/Auth/Basic.php+27 −16 modified@@ -4,9 +4,10 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace Api\Core\Auth; @@ -23,32 +24,42 @@ public function authenticate(string $realm): bool $this->api->response->addHeader('WWW-Authenticate', 'Basic realm="' . $realm . '"'); throw new \Api\Core\Exception('Web service - Applications: Unauthorized', 401); } - if (!$this->validatePass($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) { + if (!$this->api->app || !$this->validatePwd($_SERVER['PHP_AUTH_PW'])) { $this->api->response->addHeader('WWW-Authenticate', 'Basic realm="' . $realm . '"'); throw new \Api\Core\Exception('Web service - Applications: Wrong Credentials', 401); } + $apiKey = $this->api->request->getHeaders()['x-api-key'] ?? null; + if (!$apiKey || $apiKey !== \App\Encryption::getInstance()->decrypt($this->api->app['api_key'])) { + throw new \Api\Core\Exception('Invalid api key', 401); + } + return true; } + /** {@inheritdoc} */ + public function setServer(): self + { + $this->api->app = []; + $userName = $_SERVER['PHP_AUTH_USER'] ?? ''; + $type = $this->api->request->getByType('_container', \App\Purifier::STANDARD); + $query = (new \App\Db\Query())->from('w_#__servers')->where(['type' => $type, 'name' => $userName, 'status' => 1]); + if ($userName && $row = $query->one()) { + $row['id'] = (int) $row['id']; + $this->api->app = $row; + } + + return $this; + } + /** - * Validate pass. + * Validate pwd. * - * @param string $userName * @param string $password * * @return bool */ - public function validatePass(string $userName, string $password): bool + public function validatePwd(string $password): bool { - $row = (new \App\Db\Query())->from('w_#__servers')->where(['name' => $userName, 'status' => 1])->one(); - if ($row) { - $status = $password === \App\Encryption::getInstance()->decrypt($row['pass']); - if ($status) { - $row['id'] = (int) $row['id']; - $this->currentServer = $row; - } - return $status; - } - return false; + return $this->api->app && $password === \App\Encryption::getInstance()->decrypt($this->api->app['pass']); } }
api/webservice/Core/Auth/Digest.php+0 −55 removed@@ -1,55 +0,0 @@ -<?php -/** - * Digest authorization file. - * - * @package API - * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) - * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> - */ - -namespace Api\Core\Auth; - -/** - * Digest authorization class. - */ -class Digest extends AbstractAuth -{ - /** {@inheritdoc} */ - public function authenticate(string $realm): bool - { - $userpass = $this->getCredentials(); - if (!$userpass) { - $this->requireLogin(); - throw new \Api\Core\Exception('No basic authentication headers were found', 401); - } - - // Authenticates the user - if (!$this->validateUserPass($userpass[0], $userpass[1])) { - $this->requireLogin(); - throw new \Api\Core\Exception('Username or password does not match', 401); - } - $this->currentUser = $userpass[0]; - - return true; - } - - public function getCredentials() - { - $auth = $this->api->request->getHeader('authorization'); - if (!$auth) { - return null; - } - if ('basic ' !== strtolower(substr($auth, 0, 6))) { - return null; - } - return explode(':', base64_decode(substr($auth, 6)), 2); - } - - public function requireLogin() - { - $this->api->response->addHeader('WWW-Authenticate', 'Basic realm="' . $this->realm . '"'); - $this->api->response->setStatus(401); - } -}
api/webservice/Core/Auth.php+12 −6 modified@@ -4,9 +4,10 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace Api\Core; @@ -28,15 +29,20 @@ class Auth * * @param \Api\Controller $controller * - * @return array + * @return Auth\AbstractAuth */ - public static function init(\Api\Controller $controller): array + public static function init(\Api\Controller $controller): Auth\AbstractAuth { $method = \App\Config::api('AUTH_METHOD'); - $class = "Api\\Core\\Auth\\$method"; + $container = $controller->request->getByType('_container', \App\Purifier::STANDARD); + $class = "Api\\{$container}\\Auth\\{$method}"; + if (!class_exists($class)) { + $class = "Api\\Core\\Auth\\{$method}"; + } $self = new $class(); $self->setApi($controller); + $self->setServer(); $self->authenticate(static::$realm); - return $self->getCurrentServer(); + return $self; } }
api/webservice/Core/BaseAction.php+8 −18 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -189,31 +189,21 @@ public function getUserStorageId(): ?int return $this->userData['istorage'] ?? null; } - /** - * Get information, whether to check inventory levels. - * - * @return bool - */ - public function getCheckStockLevels(): bool - { - $parentId = \Api\WebservicePremium\Privilege::USER_PERMISSIONS !== $this->getPermissionType() ? $this->getParentCrmId() : 0; - return empty($parentId) || (bool) \Vtiger_Record_Model::getInstanceById($parentId)->get('check_stock_levels'); - } - /** * Get parent record. * * @throws \Api\Core\Exception * - * @return int + * @return int|null */ - public function getParentCrmId(): int + public function getParentCrmId(): ?int { if ($this->controller && ($parentId = $this->controller->request->getHeader('x-parent-id'))) { $hierarchy = new \Api\WebservicePremium\BaseModule\Hierarchy(); $hierarchy->setAllUserData($this->userData); $hierarchy->findId = $parentId; - $hierarchy->moduleName = \App\Record::getType(\App\Record::getParentRecord($this->getUserCrmId())); + $parentRecord = \App\Record::getParentRecord($this->getUserCrmId()); + $hierarchy->moduleName = $parentRecord ? '' : \App\Record::getType($parentRecord); $records = $hierarchy->get(); if (isset($records[$parentId])) { return $parentId; @@ -299,7 +289,7 @@ public function updateSession(array $data = []): void $data['ip'] = $this->controller->request->getServer('REMOTE_ADDR'); $data['parent_id'] = $this->controller->request->getHeader('x-parent-id') ?: 0; $data['last_method'] = $this->controller->request->getServer('REQUEST_URI'); - $data['agent'] = \App\TextParser::textTruncate($this->controller->request->getServer('HTTP_USER_AGENT', '-'), 100, false); + $data['agent'] = \App\TextUtils::textTruncate($this->controller->request->getServer('HTTP_USER_AGENT', '-'), 100, false); \App\Db::getInstance('webservice')->createCommand() ->update($this->controller->app['tables']['session'], $data, ['id' => $this->userData['sid']]) ->execute(); @@ -317,7 +307,7 @@ public function updateUser(array $data = []): void if (!\is_array($this->userData['custom_params'])) { $this->userData['custom_params'] = \App\Json::isEmpty($this->userData['custom_params']) ? [] : \App\Json::decode($this->userData['custom_params']); } - $this->userData['custom_params']['agent'] = \App\TextParser::textTruncate($this->controller->request->getServer('HTTP_USER_AGENT', '-'), 100, false); + $this->userData['custom_params']['agent'] = \App\TextUtils::textTruncate($this->controller->request->getServer('HTTP_USER_AGENT', '-'), 100, false); if (isset($data['custom_params'])) { $data['custom_params'] = \App\Json::encode(\App\Utils::merge($this->userData['custom_params'], $data['custom_params'])); }
api/webservice/Core/Containers.php+7 −4 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -19,12 +19,12 @@ class Containers { /** @var string[] List of available API containers */ public static $list = [ - 'WebserviceStandard', 'WebservicePremium', 'ManageConsents', + 'WebserviceStandard', 'WebservicePremium', 'ManageConsents', 'SMS', ]; /** @var string[] List of GUI tabs */ public static $listTab = [ - 'WebserviceStandard', 'WebservicePremium', 'ManageConsents', + 'WebserviceStandard', 'WebservicePremium', 'ManageConsents', 'SMS', ]; /** @var array List of db tables */ @@ -42,5 +42,8 @@ class Containers 'ManageConsents' => [ 'user' => 'w_#__manage_consents_user', ], + 'SMS' => [ + 'user' => 'w_#__sms_user', + ], ]; }
api/webservice/Core/Exception.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/Core/Module.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/Core/Request.php+4 −5 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -95,7 +95,7 @@ private function contentParse(string $content): array { $type = $this->contentType; if (!empty($type)) { - $type = explode('/', $type); + $type = explode('/', (explode(';', $type)[0])); $type = array_pop($type); } $return = []; @@ -105,8 +105,7 @@ private function contentParse(string $content): array break; case 'form-data': case 'x-www-form-urlencoded': - mb_parse_str($content, $data); - $return = $data; + $return = \Notihnio\MultipartFormDataParser\MultipartFormDataParser::parse()->params; break; } return $this->content = $return;
api/webservice/Core/Response.php+3 −3 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -114,7 +114,7 @@ public function setReasonPhrase(string $reasonPhrase): void /** * Set body data. * - * @param array|\App\Fields\File $body + * @param array $body * * @return void */
api/webservice/Core/Traits/LoginHistory.php+3 −3 modified@@ -5,8 +5,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -30,7 +30,7 @@ protected function saveLoginHistory(array $data): void ->insert($this->controller->app['tables']['loginHistory'], array_merge([ 'time' => date('Y-m-d H:i:s'), 'ip' => $this->controller->request->getServer('REMOTE_ADDR'), - 'agent' => \App\TextParser::textTruncate($this->controller->request->getServer('HTTP_USER_AGENT', '-'), 100, false), + 'agent' => \App\TextUtils::textTruncate($this->controller->request->getServer('HTTP_USER_AGENT', '-'), 100, false), 'user_name' => $this->controller->request->has('userName') ? $this->controller->request->get('userName') : $this->getUserData('user_name'), 'user_id' => $this->getUserData('id'), ],
api/webservice/Core/TwoFactorAuth.php+7 −7 modified@@ -4,14 +4,14 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ namespace Api\Core; -use Sonata\GoogleAuthenticator\GoogleAuthenticator; +use PragmaRX\Google2FA\Google2FA; /** * Two Factor Authorization class. @@ -68,14 +68,14 @@ public function generate(): array { return [ 'authMethods' => 'TOTP', - 'secretKey' => (new GoogleAuthenticator())->generateSecret(), + 'secretKey' => (new Google2FA())->generateSecretKey(), ]; } /** * Get details. * - * @return string + * @return array */ public function details(): array { @@ -109,7 +109,7 @@ public function activate(): string { $code = $this->action->controller->request->getByType('code', \App\Purifier::ALNUM); $secret = $this->action->controller->request->getByType('secret', \App\Purifier::ALNUM); - if (!(new GoogleAuthenticator())->checkCode($secret, (string) $code)) { + if (!(new Google2FA())->verifyKey($secret, (string) $code)) { return \App\Language::translate('ERR_INCORRECT_2FA_TOTP_CODE', 'Other.Exceptions'); } $this->action->updateUser([ @@ -130,7 +130,7 @@ public function activate(): string public function verify(): void { $auth = $this->action->getUserData('auth'); - if (!(new GoogleAuthenticator())->checkCode($auth['authy_secret_key'], (string) $this->action->controller->request->get('code'))) { + if (!(new Google2FA())->verifyKey($auth['authy_secret_key'], (string) $this->action->controller->request->get('code'))) { throw new \Exception('Incorrect 2FA TOTP code'); } }
api/webservice/ManageConsents/Approvals/RecordsList.php+8 −6 modified@@ -3,10 +3,10 @@ /** * Gets list of records. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -160,6 +160,7 @@ class RecordsList extends \Api\ManageConsents\BaseAction public function get() { $rawData = $records = []; + $showRaw = $this->isRawData(); $queryGenerator = $this->getQuery(); $limit = $queryGenerator->getLimit() - 1; @@ -178,10 +179,11 @@ public function get() $records[$recordModel->getId()]['id'] = $recordModel->getId(); foreach ($fields as $fieldName => $fieldModel) { $records[$recordModel->getId()][$fieldName] = $fieldModel->getUITypeModel()->getApiDisplayValue($row[$fieldName], $recordModel); + if ($showRaw) { + $rawData[$recordModel->getId()] = $recordModel->getRawValue($fieldName); + } } - if ($this->isRawData()) { - $rawData[$recordModel->getId()] = $row; - } + if ($limit === $count) { break; }
api/webservice/ManageConsents/ApprovalsRegister/Record.php+3 −3 modified@@ -2,10 +2,10 @@ /** * The file contains: Record operations. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/ManageConsents/BaseAction.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Api actions. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o. - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/ManageConsents/BaseModule/GetConsentsForEntry.php+3 −3 modified@@ -3,10 +3,10 @@ /** * Gets list of records. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/ManageConsents/BaseModule/SendEmail.php+3 −3 modified@@ -3,10 +3,10 @@ /** * Send e-mail. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/ManageConsents/Save.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Save record. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/Payments/BaseAction/ReceiveFromPaymentsSystem.php+3 −3 modified@@ -2,10 +2,10 @@ /** * The file contains: Class to handling payment information. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o. - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/SMS/Auth/Basic.php+44 −0 added@@ -0,0 +1,44 @@ +<?php +/** + * Basic authorization file. + * + * @package API + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + */ + +namespace Api\SMS\Auth; + +/** + * Basic authorization class. + */ +class Basic extends \Api\Core\Auth\Basic +{ + /** {@inheritdoc} */ + public function authenticate(string $realm): bool + { + if (!$this->api->app) { + $this->api->response->addHeader('WWW-Authenticate', 'Basic realm="' . $realm . '"'); + throw new \Api\Core\Exception('Web service - Applications: Unauthorized', 401); + } + + return true; + } + + /** {@inheritdoc} */ + public function setServer(): self + { + $this->api->app = []; + $apiKey = $this->api->request->getByType('x-api-key', \App\Purifier::ALNUM); + $type = $this->api->request->getByType('_container', \App\Purifier::STANDARD); + $query = (new \App\Db\Query())->from('w_#__servers')->where(['type' => $type, 'status' => 1]); + if ($apiKey && $row = $query->andWhere(['api_key' => \App\Encryption::getInstance()->encrypt($apiKey)])->one()) { + $row['id'] = (int) $row['id']; + $this->api->app = $row; + } + + return $this; + } +}
api/webservice/SMS/BaseAction.php+70 −0 added@@ -0,0 +1,70 @@ +<?php +/** + * Api actions. + * + * @package API + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + */ + +namespace Api\SMS; + +use OpenApi\Annotations as OA; + +/** + * BaseAction class. + * + * @OA\Info( + * title="YetiForce API for SMS. Type: SMS", + * description="", + * version="0.1", + * termsOfService="https://yetiforce.com/", + * @OA\Contact( + * email="devs@yetiforce.com", + * name="Devs API Team", + * url="https://yetiforce.com/" + * ), + * @OA\License( + * name="YetiForce Public License", + * url="https://yetiforce.com/en/yetiforce/license" + * ), + * ) + * @OA\Server( + * url="https://gitdeveloper.yetiforce.com", + * description="Demo server of the development version", + * ) + * @OA\Server( + * url="https://gitstable.yetiforce.com", + * description="Demo server of the latest stable version", + * ) + */ +class BaseAction extends \Api\Core\BaseAction +{ + /** {@inheritdoc} */ + protected function checkPermission(): void + { + $db = \App\Db::getInstance('webservice'); + $userTable = 'w_#__sms_user'; + $userData = (new \App\Db\Query()) + ->from($userTable) + ->where([ + 'server_id' => $this->controller->app['id'], + 'token' => $this->controller->request->getByType('x-token', \App\Purifier::ALNUM), + 'status' => 1, + ]) + ->limit(1)->one($db); + if (!$userData) { + throw new \Api\Core\Exception('Invalid data access', 401); + } + $this->setAllUserData($userData); + $db->createCommand()->update($userTable, ['login_time' => date('Y-m-d H:i:s')], ['id' => $userData['id']])->execute(); + \App\User::setCurrentUserId($userData['user_id']); + } + + /** {@inheritdoc} */ + public function updateSession(array $data = []): void + { + } +}
api/webservice/SMS/SMSAPI/Reception.php+112 −0 added@@ -0,0 +1,112 @@ +<?php +/** + * The file contains: Reception operations. + * + * @package API + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + */ + +namespace Api\SMS\SMSAPI; + +use OpenApi\Annotations as OA; + +/** + * Reception class. + */ +class Reception extends \Api\SMS\BaseAction +{ + /** {@inheritdoc} */ + public $allowedMethod = ['POST']; + + /** @var string Module name */ + private $moduleName = 'SMSNotifier'; + + /** {@inheritdoc} */ + protected function checkPermission(): void + { + parent::checkPermission(); + if ($this->controller->request->isEmpty('MsgId', true)) { + throw new \Api\Core\Exception('No permission - wrong data', 401); + } + } + + /** {@inheritdoc} */ + protected function checkPermissionToModule(): void + { + if (!\Api\Core\Module::checkModuleAccess($this->moduleName) || !\App\Privilege::isPermitted($this->moduleName, 'CreateView') || !($provider = \App\Integrations\SMSProvider::getDefaultProvider()) || 'SMSAPI' !== $provider->getName()) { + throw new \Api\Core\Exception('No permissions for module', 403); + } + } + + /** + * Add record. + * + * @return array + * + * @OA\Get( + * path="/webservice/SMS/SMSAPI/Reception", + * summary="Receipt of SMS", + * tags={"SMSAPI"}, + * externalDocs={ + * "description" : "SMSApi Documentation", + * "url" : "https://www.smsapi.pl/docs" + * }, + * security={ + * {"ApiKeyAuth" : {}, "token" : {}} + * }, + * @OA\Response( + * response=200, + * description="Result", + * @OA\JsonContent(ref="#/components/schemas/SMS_SMSAPI_Post_Reception") + * ), + * @OA\Response( + * response=401, + * description="`No sent token` OR `Invalid token` OR `wrong data provided in the request`", + * ), + * @OA\Response( + * response=403, + * description="No permissions for module", + * ), + * @OA\Response( + * response=405, + * description="Method Not Allowed", + * ), + * ), + * @OA\Schema( + * schema="SMS_SMSAPI_Post_Reception", + * title="Response", + * description="Response", + * type="string", + * example="OK" + * ), + */ + public function post() + { + $msgId = $this->controller->request->getByType('MsgId', \App\Purifier::ALNUM); + $message = $this->controller->request->getByType('sms_text', \App\Purifier::HTML); + $smsFrom = $this->controller->request->getByType('sms_from', \App\Purifier::DIGITS); + + $provider = \App\Integrations\SMSProvider::getProviderByName('SMSAPI'); + $queryGenerator = (new \App\QueryGenerator($this->moduleName)); + $recordId = $queryGenerator->setFields(['id'])->addCondition('msgid', $msgId, 'e')->createQuery()->scalar(); + + if ($recordId && \App\Record::isExists($recordId, $this->moduleName) + && ($recordModel = \Vtiger_Record_Model::getInstanceById($recordId, $this->moduleName)) + && $smsFrom === $provider->setPhone($recordModel->get('phone'))->get('to') + ) { + $newRecordModel = \Vtiger_Record_Model::getCleanInstance($this->moduleName); + $msgField = $newRecordModel->getField('message'); + $newRecordModel->set($msgField->getName(), $msgField->getDBValue($message)) + ->set('parentid', $recordModel->getId()) + ->set('related_to', $recordModel->get('related_to')) + ->set('smsnotifier_status', 'PLL_REPLY') + ->set('phone', $recordModel->get('phone')); + $newRecordModel->save(); + } + + echo 'OK'; + } +}
api/webservice/SMS/SMSAPI/Report.php+177 −0 added@@ -0,0 +1,177 @@ +<?php +/** + * The file contains: Report operations. + * + * @package API + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + */ + +namespace Api\SMS\SMSAPI; + +use OpenApi\Annotations as OA; + +/** + * Report class. + */ +class Report extends \Api\SMS\BaseAction +{ + /** {@inheritdoc} */ + public $allowedMethod = ['GET', 'POST']; + + /** @var string Module name */ + private $moduleName = 'SMSNotifier'; + + /** + * Get status for record by code. + * + * Statuses from api: + * 402 => 'EXPIRED', + * 403 => 'SENT', + * 404 => 'DELIVERED', + * 405 => 'UNDELIVERED', + * 406 => 'FAILED', + * 407 => 'REJECTED', + * 408 => 'UNKNOWN', + * 409 => 'QUEUE', + * 410 => 'ACCEPTED', + * 411 => 'RENEWAL', + * 412 => 'STOP'. + */ + private const STATUSES = [ + 402 => 'PLL_FAILED', + 403 => 'PLL_SENT', + 404 => 'PLL_DELIVERED', + 405 => 'PLL_FAILED', + 406 => 'PLL_FAILED', + 407 => 'PLL_FAILED', + 408 => 'PLL_SENT', + 410 => 'PLL_DELIVERED', + ]; + + /** {@inheritdoc} */ + protected function checkPermission(): void + { + parent::checkPermission(); + if (!$this->controller->request->getExploded('MsgId', ',', \App\Purifier::ALNUM) || !$this->controller->request->getExploded('status', ',', \App\Purifier::INTEGER) || !$this->controller->request->getExploded('to', ',', \App\Purifier::ALNUM)) { + throw new \Api\Core\Exception('No permission - wrong data', 401); + } + } + + /** {@inheritdoc} */ + protected function checkPermissionToModule(): void + { + if (!\Api\Core\Module::checkModuleAccess($this->moduleName) || !\App\Privilege::isPermitted($this->moduleName, 'EditView') || !($provider = \App\Integrations\SMSProvider::getDefaultProvider()) || 'SMSAPI' !== $provider->getName()) { + throw new \Api\Core\Exception('No permissions for module', 403); + } + } + + /** + * Update record status. + * + * @return void + * + * @OA\Get( + * path="/webservice/SMS/SMSAPI/Report", + * summary="Report for sms", + * tags={"SMSAPI"}, + * externalDocs={ + * "description" : "SMSApi Documentation", + * "url" : "https://www.smsapi.pl/docs" + * }, + * security={ + * {"ApiKeyAuth" : {}, "token" : {}} + * }, + * @OA\Response( + * response=200, + * description="Result", + * @OA\JsonContent(ref="#/components/schemas/SMS_SMSAPI_Get_Report") + * ), + * @OA\Response( + * response=401, + * description="`No sent token` OR `Invalid token` OR `wrong data provided in the request`", + * ), + * @OA\Response( + * response=403, + * description="No permissions for module", + * ), + * @OA\Response( + * response=405, + * description="Method Not Allowed", + * ), + * ), + * @OA\Schema( + * schema="SMS_SMSAPI_Get_Report", + * title="Response", + * description="Response", + * type="string", + * example="OK" + * ), + */ + public function get() + { + $recordIds = $this->controller->request->getExploded('idx', ',', \App\Purifier::INTEGER); + $msgIds = $this->controller->request->getExploded('MsgId', ',', \App\Purifier::ALNUM); + $statuses = $this->controller->request->getExploded('status', ',', \App\Purifier::INTEGER); + foreach ($recordIds as $key => $recordId) { + if (\App\Record::isExists($recordId, $this->moduleName) + && ($recordModel = \Vtiger_Record_Model::getInstanceById($recordId, $this->moduleName))->isEditable() + && !$recordModel->isEmpty('msgid') && \in_array($recordModel->get('msgid'), $msgIds) + && $recordModel->set('smsnotifier_status', static::STATUSES[$statuses[$key]] ?? 'PLL_UNDEFINED')->getPreviousValue() + ) { + $recordModel->save(); + } + } + + echo 'OK'; + } + + /** + * Update record status. + * + * @return void + * + * @OA\Post( + * path="/webservice/SMS/SMSAPI/Report", + * summary="Report for sms", + * tags={"SMSAPI"}, + * externalDocs={ + * "description" : "SMSApi Documentation", + * "url" : "https://www.smsapi.pl/docs" + * }, + * security={ + * {"ApiKeyAuth" : {}, "token" : {}} + * }, + * @OA\Response( + * response=200, + * description="Result", + * @OA\JsonContent(ref="#/components/schemas/SMS_SMSAPI_Post_Report") + * ), + * @OA\Response( + * response=401, + * description="`No sent token` OR `Invalid token` OR `wrong data provided in the request`", + * ), + * @OA\Response( + * response=403, + * description="No permissions for module", + * ), + * @OA\Response( + * response=405, + * description="Method Not Allowed", + * ), + * ), + * @OA\Schema( + * schema="SMS_SMSAPI_Post_Report", + * title="Response", + * description="Response", + * type="string", + * example="OK" + * ), + */ + public function post() + { + $this->get(); + } +}
api/webservice/WebservicePremium/BaseAction/Files.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/BaseAction/Install.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/BaseAction/Menu.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/BaseAction/Modules.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/CustomView.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/Dashboard.php+9 −5 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> @@ -79,14 +79,18 @@ class Dashboard extends \Api\Core\BaseAction public function get(): array { $moduleName = $this->controller->request->getModule(); + $dashboardInstance = \Api\WebservicePremium\Dashboard::getInstance($moduleName, 0, $this->controller->app['id']); + $tabs = $dashboardInstance->getTabs(); if ($this->controller->request->isEmpty('record', true)) { - $dashBoardId = \Settings_WidgetsManagement_Module_Model::getDefaultDashboard(); + $defaultDbId = \Settings_WidgetsManagement_Module_Model::getDefaultDashboard(); + $dashBoardId = isset($tabs[$defaultDbId]) ? $defaultDbId : (int) array_key_first($tabs); } else { $dashBoardId = $this->controller->request->getInteger('record'); } - $dashboardInstance = \Api\WebservicePremium\Dashboard::getInstance($moduleName, $dashBoardId, $this->controller->app['id']); + $dashboardInstance->setDashboard($dashBoardId); + return [ - 'types' => $dashboardInstance->getTabs(), + 'types' => $tabs, 'widgets' => $dashboardInstance->getData(), ]; }
api/webservice/WebservicePremium/BaseModule/Fields.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/Hierarchy.php+3 −3 modified@@ -5,8 +5,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -85,7 +85,7 @@ protected function checkPermission(): void * type="object", * @OA\Property(property="id", type="integer", example=117), * @OA\Property(property="parent", type="integer", example=0), - * @OA\Property(property="name", type="string", example="YetiForce Sp. z o.o."), + * @OA\Property(property="name", type="string", example="YetiForce S.A."), * ), * ), * ),
api/webservice/WebservicePremium/BaseModule/Pdf.php+6 −12 modified@@ -2,10 +2,10 @@ /** * Webservice premium container - Generates and downloads a PDF file from a template file. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -107,19 +107,13 @@ public function get(): array $file = $pdfFiles = $increment = []; $recordId = $this->controller->request->getInteger('record'); foreach ($this->controller->request->getArray('templates', 'Integer') as $templateId) { - $template = \Vtiger_PDF_Model::getInstanceById($templateId); + $pdf = \App\Pdf\Pdf::getInstanceByTemplateId($templateId); + $template = $pdf->getTemplate(); if (!$template || !$template->isVisible('Detail') || !$template->checkFiltersForRecord($recordId) || !$template->checkUserPermissions()) { continue; } $template->setVariable('recordId', $recordId); - $pdf = new \App\Pdf\YetiForcePDF(); - $pdf->setPageSize($template->getFormat(), $template->getOrientation()) - ->setWatermark($pdf->getTemplateWatermark($template)) - ->setFileName($template->parseVariables($template->get('filename'))) - ->parseParams($template->getParameters()) - ->loadHtml($template->parseVariables($template->getBody())) - ->setHeader($template->parseVariables($template->getHeader())) - ->setFooter($template->parseVariables($template->getFooter())); + $pdf->loadTemplateData(); $fileName = ($pdf->getFileName() ?: time()); $increment[$fileName] = $increment[$fileName] ?? 0;
api/webservice/WebservicePremium/BaseModule/PdfTemplates.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Webservice premium container - Gets a list of PDF templates file. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/Privileges.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/RecordHistory.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/Record.php+37 −8 modified@@ -4,9 +4,10 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace Api\WebservicePremium\BaseModule; @@ -19,17 +20,19 @@ class Record extends \Api\WebserviceStandard\BaseModule\Record { /** {@inheritdoc} */ - public $allowedHeaders = ['x-parent-id', 'x-header-fields']; + public $allowedHeaders = ['x-parent-id', 'x-header-fields', 'x-fields-params']; /** * Get record detail. * + * @api + * * @return array * * @OA\Get( * path="/webservice/WebservicePremium/{moduleName}/Record/{recordId}", - * summary="Data for the record", * description="Gets the details of a record", + * summary="Data for the record", * tags={"BaseModule"}, * security={{"basicAuth" : {}, "ApiKeyAuth" : {}, "token" : {}}}, * operationId="getRecord", @@ -38,6 +41,9 @@ class Record extends \Api\WebserviceStandard\BaseModule\Record * @OA\Parameter(name="X-ENCRYPTED", in="header", @OA\Schema(ref="#/components/schemas/Header-Encrypted"), required=true), * @OA\Parameter(name="x-raw-data", in="header", @OA\Schema(type="integer", enum={0, 1}), description="Gets raw data", required=false, example=1), * @OA\Parameter(name="x-parent-id", in="header", @OA\Schema(type="integer"), description="Parent record id", required=false, example=5), + * @OA\Parameter(name="x-fields-params", in="header", description="JSON array - list of fields to be returned in the specified way", required=false, + * @OA\JsonContent(ref="#/components/schemas/Fields-Settings"), + * ), * @OA\Parameter( * name="x-header-fields", * description="Get header fields", @@ -64,6 +70,13 @@ class Record extends \Api\WebserviceStandard\BaseModule\Record * @OA\XmlContent(ref="#/components/schemas/Exception"), * ), * ), + * @OA\Schema( + * schema="Fields-Settings", + * title="Custom field settings", + * description="A list of custom parameters that can affect the return value of a given field.", + * type="object", + * example={"password" : {"showHiddenData" : true}} + * ), * @OA\Schema( * schema="BaseModule_Get_Record_Response", * title="Base module - Response body for Record", @@ -177,6 +190,8 @@ public function get(): array /** * Delete record. * + * @api + * * @return bool * * @OA\Delete( @@ -213,6 +228,8 @@ public function delete(): bool /** * Edit record. * + * @api + * * @return array * * @OA\Put( @@ -230,11 +247,17 @@ public function delete(): bool * @OA\Parameter(name="moduleName", in="path", @OA\Schema(type="string"), description="Module name", required=true, example="Contacts"), * @OA\Parameter(name="recordId", in="path", @OA\Schema(type="integer"), description="Record id", required=true, example=116), * @OA\Parameter(name="X-ENCRYPTED", in="header", @OA\Schema(ref="#/components/schemas/Header-Encrypted"), required=true), - * @OA\Response(response=200, description="Contents of the response contains only id", + * @OA\Response( + * response=200, description="Contents of the response contains only id", * @OA\JsonContent(ref="#/components/schemas/BaseModule_Put_Record_Response"), * @OA\XmlContent(ref="#/components/schemas/BaseModule_Put_Record_Response"), * @OA\Link(link="GetRecordById", ref="#/components/links/GetRecordById") * ), + * @OA\Response( + * response=406, description="No input data", + * @OA\JsonContent(ref="#/components/schemas/Exception"), + * @OA\XmlContent(ref="#/components/schemas/Exception"), + * ), * ), * @OA\Schema( * schema="BaseModule_Put_Record_Response", @@ -280,11 +303,13 @@ public function put(): array /** * Create record. * + * @api + * * @return array * * @OA\Post( * path="/webservice/WebservicePremium/{moduleName}/Record", - * description="Gets data to save record", + * description="Create new record", * summary="Create record", * tags={"BaseModule"}, * security={{"basicAuth" : {}, "ApiKeyAuth" : {}, "token" : {}}}, @@ -297,12 +322,16 @@ public function put(): array * @OA\Parameter(name="moduleName", in="path", @OA\Schema(type="string"), description="Module name", required=true, example="Contacts"), * @OA\Parameter(name="X-ENCRYPTED", in="header", @OA\Schema(ref="#/components/schemas/Header-Encrypted"), required=true), * @OA\Response( - * response=200, - * description="Contents of the response contains only id", + * response=200, description="Contents of the response contains only id", * @OA\JsonContent(ref="#/components/schemas/BaseModule_Post_Record_Response"), * @OA\XmlContent(ref="#/components/schemas/BaseModule_Post_Record_Response"), * @OA\Link(link="GetRecordById", ref="#/components/links/GetRecordById") * ), + * @OA\Response( + * response=406, description="No input data", + * @OA\JsonContent(ref="#/components/schemas/Exception"), + * @OA\XmlContent(ref="#/components/schemas/Exception"), + * ), * ), * @OA\Schema( * schema="BaseModule_Post_Record_Response",
api/webservice/WebservicePremium/BaseModule/RecordRelatedList.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/RecordsList.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/RelatedModules.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/BaseModule/SaveInventory.php+17 −4 modified@@ -2,10 +2,10 @@ /** * Webservice premium container - A store functionality - creates a record in an advanced module (orders) file. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> * @author Tomasz Kur <t.kur@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> @@ -188,12 +188,25 @@ private function checkBeforeSave(): array ], ]; } - $this->inventory = new \Api\WebservicePremium\Inventory($this->moduleName, $this->controller->request->getArray('inventory'), $this->getUserStorageId(), $this->getParentCrmId()); + $this->inventory = new \Api\WebservicePremium\Inventory($this->moduleName, $this); if ($this->getCheckStockLevels() && !$this->inventory->validate()) { return [ 'errors' => $this->inventory->getErrors(), ]; } return []; } + + /** + * Get information, whether to check inventory levels. + * + * @return bool + */ + public function getCheckStockLevels(): bool + { + if (\Api\WebservicePremium\Privilege::USER_PERMISSIONS !== $this->getPermissionType() && ($parentId = $this->getParentCrmId())) { + return (bool) \Vtiger_Record_Model::getInstanceById($parentId)->get('check_stock_levels'); + } + return false; + } }
api/webservice/WebservicePremium/BaseModule/SourceBasedData.php+6 −6 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -80,14 +80,14 @@ public function put(): array $raw = $data = []; foreach ($recordModel->getModule()->getValuesFromSource($this->controller->request) as $fieldName => $value) { $recordModel->set($fieldName, $value); - $raw[$fieldName] = $value; + $raw[$fieldName] = $recordModel->getRawValue($fieldName); } - foreach ($raw as $fieldName => $value) { - $data[$fieldName] = $recordModel->getModule()->getFieldByName($fieldName)->getUITypeModel()->getApiDisplayValue($value, $recordModel); + foreach (array_keys($raw) as $fieldName) { + $data[$fieldName] = $recordModel->getModule()->getFieldByName($fieldName)->getUITypeModel()->getApiDisplayValue($recordModel->get($fieldName), $recordModel); } return [ 'data' => $data, - 'rawData' => $raw, + 'rawData' => $raw ]; } }
api/webservice/WebservicePremium/BaseModule/Widgets.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/Dashboard.php+19 −5 modified@@ -2,10 +2,10 @@ /** * Dashboard model file. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> @@ -55,6 +55,19 @@ public static function getInstance(string $moduleName, int $dashboardType, int $ return $instance; } + /** + * Set dashboard ID. + * + * @param int $dashboardType + * + * @return $this + */ + public function setDashboard(int $dashboardType): self + { + $this->dashboardType = $dashboardType; + return $this; + } + /** * Gets tabs. * @@ -68,9 +81,10 @@ public function getTabs(): array ->where(['vtiger_module_dashboard_blocks.authorized' => $this->application]) ->distinct()->createCommand()->query(); while ($dashboard = $dataReader->read()) { - $tabs[] = [ + $dbId = $dashboard['dashboard_id']; + $tabs[$dbId] = [ 'name' => \App\Language::translate($dashboard['name'], $this->moduleName), - 'id' => $dashboard['dashboard_id'], + 'id' => $dbId, 'system' => $dashboard['system'], ]; }
api/webservice/WebservicePremium/Inventory.php+29 −62 modified@@ -2,11 +2,12 @@ /** * The file contains: SaveInventory class. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o. - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ namespace Api\WebservicePremium; @@ -16,87 +17,53 @@ */ class Inventory { - /** - * Module name. - * - * @var string - */ + /** @var string Module name. */ protected $moduleName; - /** - * Inventory items passed from request. - * - * @var array - */ + /** @var array Inventory items passed from request. */ protected $inventory; - /** - * Field mapping. - * - * @var array|null - */ + /** @var array|null Field mapping. */ private $fieldMapping; - /** - * Storage. - * - * @var int - */ + /** @var int Storage ID */ protected $storage; - /** - * Products. - * - * @var array - */ + /** @var array Products */ protected $products = []; - /** - * Arrays with errors. - * - * @var array - */ + /** @var array Arrays with errors. */ protected $errors = []; - /** - * Pricebook id. - * - * @var int|null - */ - protected $pricebookId; + /** @var int|null Price book id. */ + protected $priceBookId; - /** - * Undocumented variable. - * - * @var \Vtiger_Record_Model - */ + /** @var \Vtiger_Record_Model Parent record model */ protected $parentRecordModel; - /** - * Sequence. - * - * @var int - */ + /** @var int Sequence. */ protected $seq; + /** @var int Permission type. */ + protected $permissionType; + /** * Construct. * - * @param string $moduleName - * @param array $inventory - * @param int $storage - * @param int|null $accountId + * @param string $moduleName + * @param \Api\Core\BaseAction $actionModel */ - public function __construct(string $moduleName, array $inventory, int $storage, ?int $accountId) + public function __construct(string $moduleName, \Api\Core\BaseAction $actionModel) { $this->moduleName = $moduleName; - $this->inventory = $inventory; - $this->storage = $storage; + $this->inventory = $actionModel->controller->request->getArray('inventory'); + $this->storage = $actionModel->getUserStorageId(); + $this->permissionType = $actionModel->getPermissionType(); + $accountId = $actionModel->getParentCrmId(); if (!empty($accountId)) { $this->parentRecordModel = \Vtiger_Record_Model::getInstanceById($accountId, 'Accounts'); - $this->pricebookId = $this->parentRecordModel->get('pricebook_id'); + $this->priceBookId = $this->parentRecordModel->get('pricebook_id'); } - $this->getProductsByInventory(); } @@ -270,9 +237,9 @@ private function getProductsByInventory() if (!empty($this->storage)) { $queryService->addSelect(['quantity' => new \yii\db\Expression('0')]); } - if (!$isUserPermissions && !empty($this->pricebookId)) { + if (!$isUserPermissions && !empty($this->priceBookId)) { $queryService->addSelect(['vtiger_pricebookproductrel.listprice']); - $queryService->leftJoin('vtiger_pricebookproductrel', "vtiger_pricebookproductrel.pricebookid={$this->pricebookId} AND vtiger_pricebookproductrel.productid = vtiger_service.serviceid"); + $queryService->leftJoin('vtiger_pricebookproductrel', "vtiger_pricebookproductrel.pricebookid={$this->priceBookId} AND vtiger_pricebookproductrel.productid = vtiger_service.serviceid"); } $query = (new \App\Db\Query()) ->select([ @@ -290,9 +257,9 @@ private function getProductsByInventory() $query->addSelect(['quantity' => 'u_#__istorages_products.qtyinstock']); $query->leftJoin('u_#__istorages_products', "u_#__istorages_products.crmid={$this->storage} AND u_#__istorages_products.relcrmid = vtiger_products.productid"); } - if (!$isUserPermissions && !empty($this->pricebookId)) { + if (!$isUserPermissions && !empty($this->priceBookId)) { $query->addSelect(['vtiger_pricebookproductrel.listprice']); - $query->leftJoin('vtiger_pricebookproductrel', "vtiger_pricebookproductrel.pricebookid={$this->pricebookId} AND vtiger_pricebookproductrel.productid = vtiger_products.productid"); + $query->leftJoin('vtiger_pricebookproductrel', "vtiger_pricebookproductrel.pricebookid={$this->priceBookId} AND vtiger_pricebookproductrel.productid = vtiger_products.productid"); } $dataReader = $query->createCommand()->query(); $multiCurrencyUiType = new \Vtiger_MultiCurrency_UIType();
api/webservice/WebservicePremium/ModComments/Record.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Webservice premium container - ModComments record detail file. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o. - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/Privilege.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Privilege file for client portal. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/PrivilegeQuery.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Privilege File for client portal. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/Products/Record.php+9 −6 modified@@ -2,10 +2,10 @@ /** * Webservice premium container - Loads the details of a product file. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o. - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> @@ -89,11 +89,13 @@ class Record extends \Api\WebservicePremium\BaseModule\Record * schema="Products_Get_Record_Response", * title="Base module - Response body for Record", * type="object", + * required={"status", "result"}, * @OA\Property(property="status", type="integer", enum={0, 1}, description="A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error"), * @OA\Property( * property="result", - * description="Record data", + * title="Record data", * type="object", + * required={"name", "id", "fields", "data"}, * @OA\Property(property="name", description="Record name", type="string", example="Driving school"), * @OA\Property(property="id", description="Record Id", type="integer", example=152), * @OA\Property(property="fields", type="object", title="System field names and field labels", example={"field_name_1" : "Field label 1", "field_name_2" : "Field label 2", "assigned_user_id" : "Assigned user", "createdtime" : "Created time"}, @@ -107,8 +109,9 @@ class Record extends \Api\WebservicePremium\BaseModule\Record * ), * @OA\Property( * property="privileges", - * description="Parameters determining checking of editing rights and moving to the trash", + * title="Parameters determining checking of editing rights and moving to the trash", * type="object", + * required={"isEditable", "moveToTrash"}, * @OA\Property(property="isEditable", description="Check if record is editable", type="boolean", example=true), * @OA\Property(property="moveToTrash", description="Permission to delete", type="boolean", example=false), * ), @@ -215,7 +218,7 @@ private function getProductBundles(): array $productRelationModel = \Vtiger_Relation_Model::getInstance($this->recordModel->getModule(), $this->recordModel->getModule()); $productRelationModel->set('parentRecord', $this->recordModel); $queryGenerator = $productRelationModel->getQuery(); - $queryGenerator->setField(['ean', 'taxes', 'imagename']); + $queryGenerator->setField('ean')->setField('taxes')->setField('imagename'); if ($this->isUserPermissions) { $availableTaxes = 'LBL_GROUP_TAX'; $regionalTaxes = '';
api/webservice/WebservicePremium/Products/RecordsTree.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Webservice premium container - A store functionality - gets a list of products for orders file. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o. - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com>
api/webservice/WebservicePremium/Record.php+3 −3 modified@@ -2,10 +2,10 @@ /** * The file contains: Record class. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o. - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/SSingleOrders/Delivery.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Returns price of delivery. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o. - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/Users/AccessActivityHistory.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/Users/ChangePassword.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/Users/Login.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Webservice premium container - Users Login action file. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/Users/Logout.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/Users/Preferences.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/Users/Record.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/Users/RecordsList.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
api/webservice/WebservicePremium/Users/ResetPassword.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebservicePremium/Users/TwoFactorAuth.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
api/webservice/WebserviceStandard/BaseAction/Files.php+4 −6 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> @@ -56,10 +56,6 @@ * description="Access to user methods" * ) * @OA\Tag( - * name="Products", - * description="Products methods" - * ) - * @OA\Tag( * name="Users", * description="Access to user methods" * ) @@ -75,6 +71,8 @@ class Files extends \Api\Core\BaseAction /** * Put method. * + * @api + * * @throws \Api\Core\Exception * * @return \App\Fields\File
api/webservice/WebserviceStandard/BaseAction/Modules.php+4 −2 modified@@ -5,8 +5,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -25,6 +25,8 @@ class Modules extends \Api\Core\BaseAction /** * Get permitted modules. * + * @api + * * @return array * * @OA\Get(
api/webservice/WebserviceStandard/BaseModule/CustomView.php+4 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -47,6 +47,8 @@ protected function checkPermission(): void /** * Get custom view list method. * + * @api + * * @return array * * @OA\Get(
api/webservice/WebserviceStandard/BaseModule/Fields.php+5 −8 modified@@ -5,9 +5,10 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace Api\WebserviceStandard\BaseModule; @@ -189,9 +190,7 @@ public function get(): array $block = $fieldModel->get('block'); if ($returnBlocks && !isset($blocks[$block->id])) { $blockProperties = get_object_vars($block); - $blocks[$block->id] = array_filter($blockProperties, function ($v) { - return !\is_object($v); - }); + $blocks[$block->id] = array_filter($blockProperties, fn ($v) => !\is_object($v)); $blocks[$block->id]['name'] = \App\Language::translate($block->label, $moduleName); } $fieldInfo = $fieldModel->getFieldInfo(); @@ -214,9 +213,7 @@ public function get(): array $fieldInfo['dbStructure'] = $fieldModel->getDBColumnType(false); } if ($returnQueryOperators) { - $fieldInfo['queryOperators'] = array_map(function ($value) use ($moduleName) { - return \App\Language::translate($value, $moduleName); - }, $fieldModel->getQueryOperators()); + $fieldInfo['queryOperators'] = array_map(fn ($value) => \App\Language::translate($value, $moduleName), $fieldModel->getQueryOperators()); } if (isset($fieldInfo['picklistvalues']) && $fieldModel->isEmptyPicklistOptionAllowed()) { $fieldInfo['isEmptyPicklistOptionAllowed'] = $fieldModel->isEmptyPicklistOptionAllowed();
api/webservice/WebserviceStandard/BaseModule/Privileges.php+4 −2 modified@@ -5,8 +5,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -26,6 +26,8 @@ class Privileges extends \Api\Core\BaseAction /** * Get privileges for module. * + * @api + * * @return array * * @OA\Get(
api/webservice/WebserviceStandard/BaseModule/RecordHistory.php+4 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -48,6 +48,8 @@ public function checkAction(): void /** * Get related record list method. * + * @api + * * @return array * @OA\Get( * path="/webservice/WebserviceStandard/{moduleName}/RecordHistory/{recordId}",
api/webservice/WebserviceStandard/BaseModule/Record.php+47 −15 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Arkadiusz Adach <a.adach@yetiforce.com> @@ -24,7 +24,7 @@ class Record extends \Api\Core\BaseAction public $allowedMethod = ['GET', 'DELETE', 'PUT', 'POST']; /** {@inheritdoc} */ - public $allowedHeaders = ['x-parent-id']; + public $allowedHeaders = ['x-parent-id', 'x-fields-params']; /** @var \Vtiger_Record_Model Record model instance. */ public $recordModel; @@ -75,6 +75,8 @@ protected function checkPermission(): void /** * Get record detail. * + * @api + * * @return array * * @OA\Get( @@ -89,6 +91,9 @@ protected function checkPermission(): void * @OA\Parameter(name="X-ENCRYPTED", in="header", @OA\Schema(ref="#/components/schemas/Header-Encrypted"), required=true), * @OA\Parameter(name="x-raw-data", in="header", @OA\Schema(type="integer", enum={0, 1}), description="Gets raw data", required=false, example=1), * @OA\Parameter(name="x-parent-id", in="header", @OA\Schema(type="integer"), description="Parent record id", required=false, example=5), + * @OA\Parameter(name="x-fields-params", in="header", description="JSON array - list of fields to be returned in the specified way", required=false, + * @OA\JsonContent(ref="#/components/schemas/Fields-Settings"), + * ), * @OA\Response( * response=200, * description="Gets data for the record", @@ -109,6 +114,13 @@ protected function checkPermission(): void * ), * ), * @OA\Schema( + * schema="Fields-Settings", + * title="Custom field settings", + * description="A list of custom parameters that can affect the return value of a given field.", + * type="object", + * example={"password" : {"showHiddenData" : true}} + * ), + * @OA\Schema( * schema="BaseModule_Get_Record_Response", * title="Base module - Response body for Record", * type="object", @@ -142,19 +154,19 @@ protected function checkPermission(): void */ public function get(): array { + $displayData = $fieldsLabel = []; $moduleName = $this->controller->request->get('module'); - $rawData = $this->recordModel->getData(); $setRawData = 1 === (int) ($this->controller->headers['x-raw-data'] ?? 0); - $displayData = $fieldsLabel = []; - $fields = $this->recordModel->getModule()->getFields(); - \Api\WebserviceStandard\Fields::loadWebserviceFields($fields, $this); - foreach ($fields as $fieldModel) { + $fieldParams = \App\Json::decode($this->controller->request->getHeader('x-fields-params')) ?: []; + + \Api\WebserviceStandard\Fields::loadWebserviceFields($this->recordModel->getModule(), $this); + foreach ($this->recordModel->getModule()->getFields() as $fieldModel) { if (!$fieldModel->isActiveField() || !$fieldModel->isViewable()) { continue; } $uiTypeModel = $fieldModel->getUITypeModel(); $value = $this->recordModel->get($fieldModel->getName()); - $displayData[$fieldModel->getName()] = $uiTypeModel->getApiDisplayValue($value, $this->recordModel); + $displayData[$fieldModel->getName()] = $uiTypeModel->getApiDisplayValue($value, $this->recordModel, $fieldParams[$fieldModel->getName()] ?? []); $fieldsLabel[$fieldModel->getName()] = \App\Language::translate($fieldModel->get('label'), $moduleName); } $response = [ @@ -191,6 +203,12 @@ public function get(): array } } if ($setRawData) { + $rawData = []; + foreach ($this->recordModel->getData() as $key => $value) { + if ('id' === $key || 'record_module' === $key || (($fieldModel = $this->recordModel->getField($key)) && $fieldModel->isViewable())) { + $rawData[$key] = $this->recordModel->getRawValue($key); + } + } $response['rawData'] = $rawData; } return $response; @@ -199,6 +217,8 @@ public function get(): array /** * Delete record. * + * @api + * * @return bool * * @OA\Delete( @@ -236,6 +256,8 @@ public function delete(): bool /** * Edit record. * + * @api + * * @return array * * @OA\Put( @@ -254,12 +276,16 @@ public function delete(): bool * @OA\Parameter(name="recordId", in="path", @OA\Schema(type="integer"), description="Record id", required=true, example=116), * @OA\Parameter(name="X-ENCRYPTED", in="header", @OA\Schema(ref="#/components/schemas/Header-Encrypted"), required=true), * @OA\Response( - * response=200, - * description="Contents of the response contains only id", + * response=200, description="Contents of the response contains only id", * @OA\JsonContent(ref="#/components/schemas/BaseModule_Put_Record_Response"), * @OA\XmlContent(ref="#/components/schemas/BaseModule_Put_Record_Response"), * @OA\Link(link="GetRecordById", ref="#/components/links/GetRecordById") * ), + * @OA\Response( + * response=406, description="No input data", + * @OA\JsonContent(ref="#/components/schemas/Exception"), + * @OA\XmlContent(ref="#/components/schemas/Exception"), + * ), * ), * @OA\Schema( * schema="BaseModule_Put_Record_Response", @@ -299,7 +325,7 @@ public function delete(): bool */ public function put(): array { - \Api\WebserviceStandard\Fields::loadWebserviceFields($this->recordModel->getModule()->getFields(), $this); + \Api\WebserviceStandard\Fields::loadWebserviceFields($this->recordModel->getModule(), $this); $saveModel = new \Api\WebserviceStandard\Save(); $saveModel->init($this); $saveModel->saveRecord($this->controller->request); @@ -316,11 +342,13 @@ public function put(): array /** * Create record. * + * @api + * * @return array * * @OA\Post( * path="/webservice/WebserviceStandard/{moduleName}/Record", - * description="Gets data to save record", + * description="Create new record", * summary="Create record", * tags={"BaseModule"}, * security={{"basicAuth" : {}, "ApiKeyAuth" : {}, "token" : {}}}, @@ -333,12 +361,16 @@ public function put(): array * @OA\Parameter(name="moduleName", in="path", @OA\Schema(type="string"), description="Module name", required=true, example="Contacts"), * @OA\Parameter(name="X-ENCRYPTED", in="header", @OA\Schema(ref="#/components/schemas/Header-Encrypted"), required=true), * @OA\Response( - * response=200, - * description="Contents of the response contains only id", + * response=200, description="Contents of the response contains only id", * @OA\JsonContent(ref="#/components/schemas/BaseModule_Post_Record_Response"), * @OA\XmlContent(ref="#/components/schemas/BaseModule_Post_Record_Response"), * @OA\Link(link="GetRecordById", ref="#/components/links/GetRecordById") * ), + * @OA\Response( + * response=406, description="No input data", + * @OA\JsonContent(ref="#/components/schemas/Exception"), + * @OA\XmlContent(ref="#/components/schemas/Exception"), + * ), * ), * @OA\Schema( * schema="BaseModule_Post_Record_Response",
api/webservice/WebserviceStandard/BaseModule/RecordRelatedList.php+5 −3 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -48,6 +48,8 @@ public function checkAction(): void /** * Get related record list method. * + * @api + * * @throws \Api\Core\Exception * * @return array @@ -200,7 +202,7 @@ public function get(): array $value = $relatedRecordModel->get($fieldName); $response['records'][$id][$fieldName] = $fieldModel->getUITypeModel()->getApiDisplayValue($value, $relatedRecordModel); if ($isRawData) { - $response['rawData'][$id][$fieldName] = $value; + $response['rawData'][$id][$fieldName] = $relatedRecordModel->getRawValue($fieldName); } } }
api/webservice/WebserviceStandard/BaseModule/RecordsList.php+36 −6 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -40,6 +40,8 @@ class RecordsList extends \Api\Core\BaseAction /** * Get record list method. * + * @api + * * @return array * * @OA\Get( @@ -175,7 +177,7 @@ public function createQuery(): void } $this->queryGenerator->initForCustomViewById($cvId); } else { - $this->queryGenerator->initForDefaultCustomView(); + $this->queryGenerator->initForDefaultCustomView(false, true); } $limit = 100; @@ -188,7 +190,7 @@ public function createQuery(): void } $this->queryGenerator->setLimit($limit); $this->queryGenerator->setOffset($offset); - \Api\WebserviceStandard\Fields::loadWebserviceFields($this->queryGenerator->getModuleModel()->getFields(), $this); + \Api\WebserviceStandard\Fields::loadWebserviceFields($this->queryGenerator->getModuleModel(), $this); if ($requestFields = $this->controller->request->getHeader('x-fields')) { if (!\App\Json::isJson($requestFields)) { throw new \Api\Core\Exception('Incorrect json syntax: x-fields', 400); @@ -291,10 +293,17 @@ protected function getRecordFromRow(array $row): array protected function getColumnNames(): array { $headers = []; + $selectedColumnsList = []; + if ($cvId = $this->controller->request->getHeader('x-cv-id')) { + $customViewModel = \CustomView_Record_Model::getInstanceById($cvId); + $selectedColumnsList = $customViewModel->getSelectedFields(); + } if ($this->fields) { foreach ($this->fields as $fieldName => $fieldModel) { if ($fieldModel->isViewable()) { - $headers[$fieldName] = \App\Language::translate($fieldModel->getFieldLabel(), $fieldModel->getModuleName()); + $moduleName = $fieldModel->getModuleName(); + $fieldLabel = empty($selectedColumnsList[$fieldName . ':' . $moduleName]) ? $fieldModel->getFieldLabel() : $selectedColumnsList[$fieldName . ':' . $moduleName]; + $headers[$fieldName] = \App\Language::translate($fieldLabel, $moduleName); } } } @@ -304,7 +313,9 @@ protected function getColumnNames(): array foreach ($field as $relatedFieldName) { $fieldModel = \Vtiger_Module_Model::getInstance($relatedModuleName)->getFieldByName($relatedFieldName); if ($fieldModel->isViewable()) { - $headers[$sourceField . $relatedModuleName . $relatedFieldName] = \App\Language::translate($fieldModel->getFieldLabel(), $relatedModuleName); + $selectedColumnKey = $relatedFieldName . ':' . $relatedModuleName . ':' . $sourceField; + $fieldLabel = empty($selectedColumnsList[$selectedColumnKey]) ? $fieldModel->getFieldLabel() : $selectedColumnsList[$selectedColumnKey]; + $headers[$sourceField . $relatedModuleName . $relatedFieldName] = \App\Language::translate($fieldLabel, $relatedModuleName); } } } @@ -322,6 +333,25 @@ protected function getColumnNames(): array */ protected function getRawDataFromRow(array $row): array { + foreach ($this->fields as $fieldName => $fieldModel) { + if (\array_key_exists($fieldName, $row)) { + $row[$fieldName] = $fieldModel->getUITypeModel()->getRawValue($row[$fieldName]); + } + } + if ($this->relatedFields) { + foreach ($this->relatedFields as $relatedModuleName => $fields) { + foreach ($fields as $sourceField => $field) { + foreach ($field as $relatedFieldName) { + $key = $sourceField . $relatedModuleName . $relatedFieldName; + if (\array_key_exists($key, $row)) { + $fieldModel = \Vtiger_Module_Model::getInstance($relatedModuleName)->getFieldByName($relatedFieldName); + $row[$key] = $fieldModel->getUITypeModel()->getRawValue($row[$key]); + } + } + } + } + } + return $row; } }
api/webservice/WebserviceStandard/BaseModule/RelatedModules.php+4 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -24,6 +24,8 @@ class RelatedModules extends \Api\Core\BaseAction /** * Get related modules list method. * + * @api + * * @return array * * @OA\Get(
api/webservice/WebserviceStandard/Fields.php+19 −16 modified@@ -2,10 +2,10 @@ /** * File with custom functionality for fields. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -22,14 +22,15 @@ class Fields /** * Load custom fields data for the webservice app. * - * @param \Vtiger_Field_Model[] $fields - * @param \Api\Core\BaseAction $actionModel + * @param \Vtiger_Module_Model $moduleModel + * @param \Api\Core\BaseAction $actionModel * * @return void */ - public static function loadWebserviceFields(array $fields, \Api\Core\BaseAction $actionModel): void + public static function loadWebserviceFields(\Vtiger_Module_Model $moduleModel, \Api\Core\BaseAction $actionModel): void { - foreach (self::getFields($actionModel->controller->app['id']) as $fieldName => $fieldData) { + $fields = $moduleModel->getFields(); + foreach (self::getFields($actionModel->controller->app['id'], $moduleModel->getId()) as $fieldName => $fieldData) { if (isset($fields[$fieldName])) { self::loadWebserviceByField($fields[$fieldName], $actionModel, $fieldData); } @@ -48,7 +49,7 @@ public static function loadWebserviceFields(array $fields, \Api\Core\BaseAction public static function loadWebserviceByField(\Vtiger_Field_Model $fieldModel, \Api\Core\BaseAction $actionModel, ?array $fieldData = null): void { if (null === $fieldData) { - $fieldData = self::getFields($actionModel->controller->app['id'])[$fieldModel->getName()] ?? []; + $fieldData = self::getFields($actionModel->controller->app['id'], $fieldModel->getModuleId())[$fieldModel->getName()] ?? []; } if ($fieldData) { if (1 !== $actionModel->getUserData('type') && !empty($fieldData['is_default'])) { @@ -64,24 +65,26 @@ public static function loadWebserviceByField(\Vtiger_Field_Model $fieldModel, \A * Get fields for current webservice app. * * @param int $serverId + * @param int $moduleId * * @return array */ - public static function getFields(int $serverId): array + public static function getFields(int $serverId, int $moduleId): array { - if (isset(self::$webserviceAppsFields[$serverId])) { - return self::$webserviceAppsFields[$serverId]; + $cacheKey = "{$serverId}_{$moduleId}"; + if (isset(self::$webserviceAppsFields[$cacheKey])) { + return self::$webserviceAppsFields[$cacheKey]; } - if (\App\Cache::has('WebserviceAppsFields', $serverId)) { - return \App\Cache::get('WebserviceAppsFields', $serverId); + if (\App\Cache::has('WebserviceAppsFields', $cacheKey)) { + return \App\Cache::get('WebserviceAppsFields', $cacheKey); } - self::$webserviceAppsFields[$serverId] = $response = (new \App\Db\Query())->select(['vtiger_field.fieldname', 'w_#__fields_server.*']) + self::$webserviceAppsFields[$cacheKey] = $response = (new \App\Db\Query())->select(['vtiger_field.fieldname', 'w_#__fields_server.*']) ->from('w_#__fields_server') - ->where(['w_#__fields_server.serverid' => $serverId]) + ->where(['w_#__fields_server.serverid' => $serverId, 'vtiger_field.tabid' => $moduleId]) ->innerJoin('vtiger_field', 'w_#__fields_server.fieldid = vtiger_field.fieldid') ->indexBy('fieldname') ->all(\App\Db::getInstance('webservice')) ?: []; - \App\Cache::save('WebserviceAppsFields', $serverId, $response); + \App\Cache::save('WebserviceAppsFields', $cacheKey, $response); return $response; }
api/webservice/WebserviceStandard/Save.php+9 −5 modified@@ -2,10 +2,10 @@ /** * Action file to save record. * - * @package Api + * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -19,6 +19,7 @@ class Save extends \Vtiger_Save_Action { /** @var int ID of application. */ protected $appId; + /** @var array Skipped value. */ public $skippedData = []; @@ -32,11 +33,11 @@ public function __construct() /** * Initialization with API data. * - * @param BaseModule\Record $record + * @param BaseModule\Record|Users\Record $record * * @return void */ - public function init(BaseModule\Record $record): void + public function init(\Api\Core\BaseAction $record): void { $this->appId = $record->controller->app['id']; $this->record = $record->recordModel; @@ -48,6 +49,9 @@ protected function getRecordModelFromRequest(\App\Request $request) $fieldModelList = $this->record->getModule()->getFields(); $requestKeys = $request->getAllRaw(); unset($requestKeys['module'],$requestKeys['action'],$requestKeys['record']); + if (empty($requestKeys)) { + throw new \Api\Core\Exception('No input data', 406); + } foreach ($fieldModelList as $fieldName => $fieldModel) { if (!$fieldModel->isWritable()) { continue;
api/webservice/WebserviceStandard/Users/AccessActivityHistory.php+5 −3 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -32,6 +32,8 @@ protected function checkPermissionToModule(): void /** * Get user history of access activity. * + * @api + * * @return array * * @OA\Get( @@ -95,7 +97,7 @@ public function get(): array while ($row = $dataReader->read()) { $rows[] = [ 'time' => \App\Fields\DateTime::formatToDisplay($row['time']), - 'status' => \App\Language::translate($row['status'], 'Settings.WebserviceUsers'), + 'status' => \App\Language::translate($row['status'], 'Settings:WebserviceUsers'), 'agent' => $row['agent'], 'ip' => $row['ip'], ];
api/webservice/WebserviceStandard/Users/ChangePassword.php+4 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -31,6 +31,8 @@ protected function checkPermissionToModule(): void /** * Put method. * + * @api + * * @return bool * * @OA\Put(
api/webservice/WebserviceStandard/Users/Login.php+6 −4 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -39,6 +39,8 @@ protected function checkPermissionToModule(): void /** * Post method. * + * @api + * * @throws \Api\Core\Exception * * @return array|null @@ -356,7 +358,7 @@ protected function createSession(): void 'params' => \App\Json::encode($params), 'ip' => $this->controller->request->getServer('REMOTE_ADDR'), 'last_method' => $this->controller->request->getServer('REQUEST_URI'), - 'agent' => \App\TextParser::textTruncate($this->controller->request->getServer('HTTP_USER_AGENT', '-'), 100, false), + 'agent' => \App\TextUtils::textTruncate($this->controller->request->getServer('HTTP_USER_AGENT', '-'), 100, false), ])->execute(); } @@ -371,7 +373,7 @@ protected function checkAccess(): void { $db = \App\Db::getInstance('webservice'); $userData = (new \App\Db\Query())->from($this->controller->app['tables']['user']) - ->where(['user_name' => $this->controller->request->get('userName'), 'status' => 1]) + ->where(['server_id' => $this->controller->app['id'], 'user_name' => $this->controller->request->get('userName'), 'status' => 1]) ->limit(1)->one($db); if (!$userData) { $this->saveLoginHistory([
api/webservice/WebserviceStandard/Users/Logout.php+4 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -30,6 +30,8 @@ protected function checkPermissionToModule(): void /** * Put method. * + * @api + * * @return bool * * @OA\Put(
api/webservice/WebserviceStandard/Users/Record.php+106 −16 modified@@ -4,9 +4,10 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace Api\WebserviceStandard\Users; @@ -19,33 +20,37 @@ class Record extends \Api\Core\BaseAction { /** {@inheritdoc} */ - public $allowedMethod = ['GET']; + public $allowedMethod = ['GET', 'POST']; /** @var \Users_Record_Model User record model. */ public $recordModel; - /** - * Check permission to method, access for administrators only. - * - * @throws \Api\Core\Exception - * - * @return bool - */ + /** {@inheritdoc} */ protected function checkPermission(): void { parent::checkPermission(); - if ($this->controller->request->isEmpty('record', true) || !\App\User::isExists($this->controller->request->getInteger('record'), false)) { - throw new \Api\Core\Exception('User doesn\'t exist', 404); - } - if (!\App\User::getCurrentUserModel()->isAdmin()) { - throw new \Api\Core\Exception('Access denied, access for administrators only', 403); + $moduleName = $this->controller->request->getModule(); + if ('POST' === $this->controller->method) { + $this->recordModel = \Users_Record_Model::getCleanInstance($moduleName); + if (!$this->recordModel->isCreateable()) { + throw new \Api\Core\Exception('No permissions to create user', 403); + } + } else { + if ($this->controller->request->isEmpty('record', true) || !\App\User::isExists($this->controller->request->getInteger('record'), false)) { + throw new \Api\Core\Exception('User doesn\'t exist', 404); + } + if (!\App\User::getCurrentUserModel()->isAdmin()) { + throw new \Api\Core\Exception('Access denied, access for administrators only', 403); + } + $this->recordModel = \Users_Record_Model::getInstanceById($this->controller->request->getInteger('record'), 'Users'); } - $this->recordModel = \Users_Record_Model::getInstanceById($this->controller->request->getInteger('record'), 'Users'); } /** * Get user detail. * + * @api + * * @return array * * @OA\Get( @@ -54,6 +59,7 @@ protected function checkPermission(): void * summary="Data for the user", * tags={"Users"}, * security={{"basicAuth" : {}, "ApiKeyAuth" : {}, "token" : {}}}, + * operationId="getUser", * @OA\Parameter( * name="userId", * description="User id", @@ -146,4 +152,88 @@ public function get(): array } return $response; } + + /** + * Create record. + * + * @api + * + * @return array + * + * @OA\Post( + * path="/webservice/WebserviceStandard/Users/Record", + * description="Create new user", + * summary="Create user", + * tags={"Users"}, + * security={{"basicAuth" : {}, "ApiKeyAuth" : {}, "token" : {}}}, + * @OA\RequestBody(required=true, description="Contents of the request contains an associative array with the user data.", + * @OA\JsonContent(ref="#/components/schemas/User_Create_Details"), + * @OA\XmlContent(ref="#/components/schemas/User_Create_Details"), + * ), + * @OA\Parameter(name="X-ENCRYPTED", in="header", @OA\Schema(ref="#/components/schemas/Header-Encrypted"), required=true), + * @OA\Response( + * response=200, description="Contents of the response contains only id", + * @OA\JsonContent(ref="#/components/schemas/User_Post_Record_Response"), + * @OA\XmlContent(ref="#/components/schemas/User_Post_Record_Response"), + * @OA\Link(link="GetUserById", ref="#/components/links/GetUserById") + * ), + * @OA\Response( + * response=406, description="No input data", + * @OA\JsonContent(ref="#/components/schemas/Exception"), + * @OA\XmlContent(ref="#/components/schemas/Exception"), + * ), + * ), + * @OA\Schema( + * schema="User_Post_Record_Response", + * title="User - Created user", + * description="Contents of the response contains only id and name", + * type="object", + * required={"status", "result"}, + * @OA\Property(property="status", type="integer", enum={0, 1}, description="A numeric value of 0 or 1 that indicates whether the communication is valid. 1 - success , 0 - error"), + * @OA\Property(property="result", type="object", title="User data", description="Created user id and name.", + * required={"id", "name"}, + * @OA\Property(property="id", type="integer", description="Id of the newly created user", example=22), + * @OA\Property(property="name", type="string", description="Id of the newly created user", example="YetiForce Name"), + * @OA\Property(property="skippedData", type="object", description="List of parameters passed in the request that were skipped in the write process"), + * ), + * ), + * @OA\Schema( + * schema="User_Create_Details", + * title="General - User create details", + * description="User data in user format for create view", + * type="object", + * example={"user_name" : "tom", "first_name" : "Tom", "last_name" : "Kowalski", "roleid" : "H38", "password" : "MyFunP@ssword", "confirm_password" : "MyFunP@ssword", "email1" : "my@email.com", "language" : "en-US"}, + * ), + * @OA\Link( + * link="GetUserById", + * description="The `id` value returned in the response can be used as the `userId` parameter in `GET /webservice/Users/Record/{userId}`.", + * operationId="getUser", + * parameters={ + * "recordId" = "$response.body#/result/id" + * } + * ) + */ + public function post(): array + { + if (1 !== $this->getUserData('type')) { + foreach ($this->recordModel->getModule()->getFieldsByType('serverAccess') as $fieldName => $fieldModel) { + if ($fieldModel->getFieldParams() == $this->getUserData('server_id')) { + $this->recordModel->set($fieldName, 1); + break; + } + } + } + \Api\WebserviceStandard\Fields::loadWebserviceFields($this->recordModel->getModule(), $this); + $saveModel = new \Api\WebserviceStandard\Save(); + $saveModel->init($this); + $saveModel->saveRecord($this->controller->request); + $return = [ + 'id' => $this->recordModel->getId(), + 'name' => $this->recordModel->getName(), + ]; + if ($saveModel->skippedData) { + $return['skippedData'] = $saveModel->skippedData; + } + return $return; + } }
api/webservice/WebserviceStandard/Users/RecordsList.php+10 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -37,6 +37,8 @@ class RecordsList extends \Api\Core\BaseAction /** * Get users list method. * + * @api + * * @return array * * @OA\Get( @@ -250,6 +252,12 @@ protected function getColumnNames(): array */ protected function getRawDataFromRow(array $row): array { + foreach ($this->fields as $fieldName => $fieldModel) { + if (\array_key_exists($fieldName, $row)) { + $row[$fieldName] = $fieldModel->getUITypeModel()->getRawValue($row[$fieldName]); + } + } + return $row; } }
api/webservice/WebserviceStandard/Users/ResetPassword.php+6 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -36,6 +36,8 @@ protected function checkPermissionToModule(): void /** * Post method. * + * @api + * * @return bool * * @OA\Post( @@ -138,6 +140,8 @@ public function post(): array /** * Put method. * + * @api + * * @return bool * * @OA\Put(
api/webservice/WebserviceStandard/Users/TwoFactorAuth.php+8 −2 modified@@ -4,8 +4,8 @@ * * @package API * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -31,6 +31,8 @@ protected function checkPermissionToModule(): void /** * Get two factor authentication details. * + * @api + * * @return array * * @OA\Get( @@ -99,6 +101,8 @@ public function get(): array /** * Post method. * + * @api + * * @throws \Api\Core\Exception * * @return array @@ -175,6 +179,8 @@ public function post(): string /** * Delete record. * + * @api + * * @return bool * * @OA\Delete(
app/Anonymization.php+3 −3 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -42,7 +42,7 @@ public static function getTypes(): array * @var array Word map for anonymization. */ const MAPS = [ - 'password' => ['pass', 'password', 'oldPassword'], + 'password' => ['pass', 'password', 'oldPassword', 'retype_password', 'db_password'], ]; /** * @var string Map name
app/AutoAssign.php+9 −9 modified@@ -7,8 +7,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -40,9 +40,9 @@ class AutoAssign extends Base public const MODE_WORKFLOW = 4; /** @var int Load balance method */ - private const METHOD_LOAD_BALANCE = 0; + public const METHOD_LOAD_BALANCE = 0; /** @var int Round robin method */ - private const METHOD_ROUND_ROBIN = 1; + public const METHOD_ROUND_ROBIN = 1; /** * Get all auto assign entries for module. @@ -207,14 +207,14 @@ public function isActive(int $mode): bool * * @return int */ - public function getOwner(): int + public function getOwner(): ?int { switch ($this->get('method')) { case self::METHOD_LOAD_BALANCE: - $owner = $this->getQueryByLoadBalance()->scalar(); + $owner = $this->getQueryByLoadBalance()->scalar() ?: null; break; case self::METHOD_ROUND_ROBIN: - $owner = $this->getQueryByRoundRobin()->scalar(); + $owner = $this->getQueryByRoundRobin()->scalar() ?: null; break; default: $owner = null; @@ -239,7 +239,7 @@ public function getOwners(): array $owner = $this->getQueryByRoundRobin()->all(); break; default: - $owner = []; + $owner = []; break; } @@ -417,7 +417,7 @@ public function postProcess(int $userId) $isExists = (new Db\Query())->from(self::ROUND_ROBIN_TABLE)->where($params)->exists(); if ($isExists) { $dbCommand->update(self::ROUND_ROBIN_TABLE, ['datetime' => (new \DateTime())->format('Y-m-d H:i:s.u')], $params)->execute(); - } else { + } elseif (\App\User::isExists($userId, false)) { $params['datetime'] = (new \DateTime())->format('Y-m-d H:i:s.u'); $dbCommand->insert(self::ROUND_ROBIN_TABLE, $params)->execute(); }
app/Automatic/RecordFlowUpdater.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> */
app/Automatic/Rules.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> */
app/Automatic/RulesPicklist.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> */
app/Base.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/BatchMethod.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Cache/Apcu.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Cache/Base.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Cache.php+11 −11 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -58,7 +58,7 @@ public static function init() * * @return mixed */ - public static function get($nameSpace, $key) + public static function get(string $nameSpace, string $key) { return static::$pool->get("$nameSpace-$key"); } @@ -71,7 +71,7 @@ public static function get($nameSpace, $key) * * @return bool */ - public static function has($nameSpace, $key): bool + public static function has(string $nameSpace, string $key): bool { return static::$pool->has("$nameSpace-$key"); } @@ -86,7 +86,7 @@ public static function has($nameSpace, $key): bool * * @return bool */ - public static function save($nameSpace, $key, $value = null, $duration = self::MEDIUM) + public static function save(string $nameSpace, string $key, $value = null, $duration = self::MEDIUM) { if (!static::$pool->save("$nameSpace-$key", $value, $duration)) { Log::warning("Error writing to cache. Key: $nameSpace-$key | Value: " . var_export($value, true)); @@ -102,7 +102,7 @@ public static function save($nameSpace, $key, $value = null, $duration = self::M * * @return bool */ - public static function delete($nameSpace, $key) + public static function delete(string $nameSpace, string $key) { static::$pool->delete("$nameSpace-$key"); } @@ -125,7 +125,7 @@ public static function clear(): bool * * @return mixed */ - public static function staticGet($nameSpace, $key) + public static function staticGet(string $nameSpace, string $key = '') { return static::$staticPool->get("$nameSpace-$key"); } @@ -138,7 +138,7 @@ public static function staticGet($nameSpace, $key) * * @return bool */ - public static function staticHas($nameSpace, $key = '') + public static function staticHas(string $nameSpace, string $key = '') { return static::$staticPool->has("$nameSpace-$key"); } @@ -153,7 +153,7 @@ public static function staticHas($nameSpace, $key = '') * * @return bool */ - public static function staticSave($nameSpace, $key, $value = null) + public static function staticSave(string $nameSpace, string $key, $value = null) { return static::$staticPool->save("$nameSpace-$key", $value); } @@ -166,7 +166,7 @@ public static function staticSave($nameSpace, $key, $value = null) * * @return bool */ - public static function staticDelete($nameSpace, $key) + public static function staticDelete(string $nameSpace, string $key) { static::$staticPool->delete("$nameSpace-$key"); } @@ -262,7 +262,7 @@ public static function clearTemporaryFiles(string $days = '-30 day'): array } foreach ([ROOT_DIRECTORY . '/cache', \App\Fields\File::getTmpPath()] as $dir) { foreach ((new \DirectoryIterator($dir)) as $item) { - if ($item->isFile() && 'index.html' !== $item->getBasename()) { + if ($item->isFile() && 'index.html' !== $item->getBasename() && $item->getMTime() < $time && $item->getATime() < $time) { $s += $item->getSize(); unlink($item->getPathname()); ++$i;
app/Cache/XCache.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Chat.php+4 −6 modified@@ -5,8 +5,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> * @author Tomasz Poradzewski <t.poradzewski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> @@ -142,7 +142,7 @@ public static function setCurrentRoomDefault() /** * Get current room ID, type. * - * @return []|false + * @return array|false */ public static function getCurrentRoom() { @@ -698,9 +698,7 @@ public static function getNumberOfNewMessages(?array $roomInfo = null): array } } - $lastMessage = 1 === \count($lastMessagesData) ? current($lastMessagesData) : array_reduce($lastMessagesData, function ($a, $b) { - return $a['created'] > $b['created'] ? $a : $b; - }); + $lastMessage = 1 === \count($lastMessagesData) ? current($lastMessagesData) : array_reduce($lastMessagesData, fn ($a, $b) => $a['created'] > $b['created'] ? $a : $b); if (!empty($lastMessage)) { $lastMessage['messages'] = static::decodeNoHtmlMessage($lastMessage['messages'], false); $lastMessage['userData'] = static::getUserInfo($lastMessage['userid']);
app/Cli/Base.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Base cli file. * - * @package App + * @package Cli * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Cli/Cleaner.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Cleaner cli file. * - * @package App + * @package Cli * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Cli/Environment.php+6 −10 modified@@ -2,10 +2,10 @@ /** * Environment cli file. * - * @package App + * @package Cli * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -81,7 +81,7 @@ public function confReportAll(): void $value = \is_array($value) ? \App\Json::encode($value) : $value; $table[] = [ 'Parameter' => $item['status'] ? $name : "<light_red>{$name}</light_red>", - 'Recommended' => $item['recommended'] ? print_r($item['recommended'], true) : '-', + 'Recommended' => empty($item['recommended']) ? '-' : print_r($item['recommended'], true), 'Value' => $item['status'] ? $value : ("<light_red>{$value}</light_red>"), ]; } @@ -104,14 +104,10 @@ public function confReportAll(): void public function htmlToText(array &$item): void { if (false !== strpos($item['val'], '<b class="text-danger">')) { - $item['val'] = preg_replace_callback("'<b class=\"text-danger\">(.*?)</b>'si", function ($match) { - return "<light_red>{$match['1']}</light_red>"; - }, $item['val']); + $item['val'] = preg_replace_callback("'<b class=\"text-danger\">(.*?)</b>'si", fn ($match) => "<light_red>{$match['1']}</light_red>", $item['val']); } if (false !== strpos($item['recommended'], '<b class="text-danger">')) { - $item['recommended'] = preg_replace_callback("'<b class=\"text-danger\">(.*?)</b>'si", function ($match) { - return "<light_red>{$match['1']}</light_red>"; - }, $item['recommended']); + $item['recommended'] = preg_replace_callback("'<b class=\"text-danger\">(.*?)</b>'si", fn ($match) => "<light_red>{$match['1']}</light_red>", $item['recommended']); } } }
app/Cli.php+3 −3 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -67,7 +67,7 @@ public function exec($command, $full = false) $this->climate->white('Version: ' . Version::get() . ' | CRM URL: ' . \Config\Main::$site_URL); $this->climate->lightGreen()->border('─', 200); \App\User::setCurrentUserId(\Users::getActiveAdminId()); - \App\Language::setTemporaryLanguage('en_US'); + \App\Language::setTemporaryLanguage('en-US'); $this->climate->arguments->add([ 'module' => [
app/Cli/Roundcube.php+70 −0 added@@ -0,0 +1,70 @@ +<?php +/** + * Roundcube cli file. + * + * @package Cli + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Cli; + +/** + * Roundcube cli class. + */ +class Roundcube extends Base +{ + /** {@inheritdoc} */ + public $moduleName = 'Roundcube'; + + /** @var string[] Methods list */ + public $methods = [ + 'clearUsersPreferences' => 'Clear users preferences', + 'clearUsersCache' => 'Clear users cache', + 'clearUsersSession' => 'Clear users session', + ]; + + /** + * Clear users preferences. + * + * @return void + */ + public function clearUsersPreferences(): void + { + \App\Db::getInstance()->createCommand()->update('roundcube_users', ['preferences' => ''])->execute(); + if (!$this->climate->arguments->defined('action')) { + $this->cli->actionsList('Roundcube'); + } + } + + /** + * Clear users cache. + * + * @return void + */ + public function clearUsersCache(): void + { + $createCommand = \App\Db::getInstance()->createCommand(); + foreach (['roundcube_cache', 'roundcube_cache_index', 'roundcube_cache_messages', 'roundcube_cache_shared', 'roundcube_cache_thread'] as $table) { + $createCommand->truncateTable($table)->execute(); + } + if (!$this->climate->arguments->defined('action')) { + $this->cli->actionsList('Roundcube'); + } + } + + /** + * Clear users session. + * + * @return void + */ + public function clearUsersSession(): void + { + \App\Db::getInstance()->createCommand()->truncateTable('roundcube_session')->execute(); + if (!$this->climate->arguments->defined('action')) { + $this->cli->actionsList('Roundcube'); + } + } +}
app/Cli/System.php+6 −6 modified@@ -2,10 +2,10 @@ /** * System cli file. * - * @package App + * @package Cli * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -168,7 +168,7 @@ private function updateByPackage(array $package): void if ($packageInstance->_errorText) { $this->climate->lightRed($packageInstance->_errorText); } else { - echo $response; + echo $response . PHP_EOL; } } catch (\Throwable $th) { $this->climate->lightRed($th->__toString()); @@ -183,8 +183,8 @@ private function updateByPackage(array $package): void */ public function checkRegStatus(): void { - $status = \App\YetiForce\Register::check(true); - $this->climate->bold('Status: ' . \App\Language::translate(\App\YetiForce\Register::STATUS_MESSAGES[$status], 'Settings::Companies')); + \App\YetiForce\Register::check(true); + $this->climate->bold('Status: ' . \App\Language::translate(\App\YetiForce\Register::STATUS_MESSAGES[\App\YetiForce\Register::getStatus()], 'Settings::Companies')); $this->climate->border('─', 200); $this->climate->bold('APP ID: ' . \App\YetiForce\Register::getInstanceKey()); $this->climate->border('─', 200);
app/Cli/Users.php+3 −3 modified@@ -2,10 +2,10 @@ /** * Users cli file. * - * @package App + * @package Cli * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Colors.php+18 −23 modified@@ -4,10 +4,11 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Sławomir Kłos <s.klos@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace App; @@ -38,7 +39,7 @@ public static function generate($type = 'all') case 'picklist': static::generatePicklists(); break; - case 'field': + case 'field': static::generateFields(); break; default: @@ -58,15 +59,15 @@ private static function generateOwners() $css = ''; $colors = []; foreach (static::getAllUserColor() as $item) { - if (ltrim($item['color'], '#')) { + if (null !== $item['color'] && ltrim($item['color'], '#')) { $css .= '.ownerCBg_' . $item['id'] . ' { background: ' . $item['color'] . ' !important; font-weight: 500 !important; color: ' . static::getContrast($item['color']) . ' !important;}' . PHP_EOL; $css .= '.ownerCT_' . $item['id'] . ' { color: ' . $item['color'] . ' !important; }' . PHP_EOL; $css .= '.ownerCBr_' . $item['id'] . ' { border-color: ' . $item['color'] . ' !important; }' . PHP_EOL; $colors[$item['id']] = $item['color']; } } foreach (static::getAllGroupColor() as $item) { - if (ltrim($item['color'], '#')) { + if (null !== $item['color'] && ltrim($item['color'], '#')) { $css .= '.ownerCBg_' . $item['id'] . ' { background: ' . $item['color'] . ' !important; font-weight: 500 !important; color: ' . static::getContrast($item['color']) . ' !important;}' . PHP_EOL; $css .= '.ownerCT_' . $item['id'] . ' { color: ' . $item['color'] . ' !important; }' . PHP_EOL; $css .= '.ownerCBr_' . $item['id'] . ' { border-color: ' . $item['color'] . ' !important; }' . PHP_EOL; @@ -103,20 +104,17 @@ private static function generatePicklists() $fields = static::getPicklistFieldsByModule($module['tabname']); foreach ($fields as $field) { $values = \App\Fields\Picklist::getValues($field->getName()); - if ($values) { - $firstRow = reset($values); - if (\array_key_exists('color', $firstRow)) { - foreach ($values as $item) { - if (ltrim($item['color'], '#')) { - if (false === strpos($item['color'], '#')) { - $item['color'] = '#' . $item['color']; - } - $contrastColor = static::getContrast($item['color']); - $css .= '.picklistCBr_' . $module['tabname'] . '_' . static::sanitizeValue($field->getName()) . '_' . static::sanitizeValue($item['picklistValue']) . ' { border-color: ' . $item['color'] . ' !important; }' . PHP_EOL; - $css .= '.picklistCT_' . $module['tabname'] . '_' . static::sanitizeValue($field->getName()) . '_' . static::sanitizeValue($item['picklistValue']) . ' { color: ' . $item['color'] . ' !important; }' . PHP_EOL; - $css .= '.picklistCBg_' . $module['tabname'] . '_' . static::sanitizeValue($field->getName()) . '_' . static::sanitizeValue($item['picklistValue']) . ' { background: ' . $item['color'] . ' !important; font-weight: 500 !important; color: ' . $contrastColor . ' !important;}' . PHP_EOL; - $css .= '.picklistLb_' . $module['tabname'] . '_' . static::sanitizeValue($field->getName()) . '_' . static::sanitizeValue($item['picklistValue']) . ' { background: ' . $item['color'] . ' !important; font-weight: 500 !important; color: ' . $contrastColor . ' !important; padding: 2px 7px 3px 7px;}' . PHP_EOL; + if ($values && ($firstRow = reset($values)) && \array_key_exists('color', $firstRow)) { + foreach ($values as $item) { + if (($color = $item['color'] ?? '') && '#' !== $color) { + if (false === strpos($color, '#')) { + $color = '#' . $color; } + $contrastColor = static::getContrast($color); + $css .= '.picklistCBr_' . $module['tabname'] . '_' . static::sanitizeValue($field->getName()) . '_' . static::sanitizeValue($item['picklistValue']) . ' { border-color: ' . $color . ' !important; }' . PHP_EOL; + $css .= '.picklistCT_' . $module['tabname'] . '_' . static::sanitizeValue($field->getName()) . '_' . static::sanitizeValue($item['picklistValue']) . ' { color: ' . $color . ' !important; }' . PHP_EOL; + $css .= '.picklistCBg_' . $module['tabname'] . '_' . static::sanitizeValue($field->getName()) . '_' . static::sanitizeValue($item['picklistValue']) . ' { background: ' . $color . ' !important; font-weight: 500 !important; color: ' . $contrastColor . ' !important;}' . PHP_EOL; + $css .= '.picklistLb_' . $module['tabname'] . '_' . static::sanitizeValue($field->getName()) . '_' . static::sanitizeValue($item['picklistValue']) . ' { background: ' . $color . ' !important; font-weight: 500 !important; color: ' . $contrastColor . ' !important; padding: 2px 7px 3px 7px;}' . PHP_EOL; } } } @@ -150,12 +148,9 @@ public static function get($color, $value) * * @param string $value */ - public static function sanitizeValue($value) + public static function sanitizeValue($value): string { - if (empty($value)) { - return $value; - } - return str_replace([' ', '-', '=', '+', '@', '*', '!', '#', '$', '%', '^', '&', '(', ')', '[', ']', '{', '}', ';', ':', "\\'", '"', ',', '<', '.', '>', '/', '?', '\\', '|'], '_', \App\Utils::sanitizeSpecialChars($value)); + return empty($value) ? '' : str_replace([' ', '-', '=', '+', '@', '*', '!', '#', '$', '%', '^', '&', '(', ')', '[', ']', '{', '}', ';', ':', "\\'", '"', ',', '<', '.', '>', '/', '?', '\\', '|'], '_', \App\Utils::sanitizeSpecialChars($value)); } /**
app/Company.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Components/InterestsConflict.php+6 −8 modified@@ -5,8 +5,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -217,7 +217,7 @@ public static function unlock(int $baseRecord, int $sourceRecord, string $commen 'to' => \Config\Components\InterestsConflict::$notificationsEmails, 'dateTime' => date('Y-m-d H:i:s'), 'user' => \App\User::getCurrentUserModel()->getName(), - 'record' => \App\Layout::getRecordLabel($baseRecord), + 'record' => \App\Record::getHtmlLink($baseRecord), 'comment' => nl2br($comment), ]); } @@ -298,7 +298,7 @@ public static function updateUnlockStatus(int $id, int $status): void 'moduleName' => 'Users', 'recordId' => $row['user_id'], 'to' => $userModel->getDetail('email1'), - 'record' => \App\Layout::getRecordLabel($row['related_id']), + 'record' => \App\Record::getHtmlLink($row['related_id']), 'status' => \App\Language::translate(self::UNLOCK_STATUS_LABELS[$status], '_Base', $userModel->getDetail('language')), ]); } @@ -315,10 +315,8 @@ public static function getModules(): array if (\App\Cache::has($cacheName, '')) { return \App\Cache::get($cacheName, ''); } - $allModules = array_map(function ($v) { - return 0 > $v ? 999 : sprintf('%03d', $v); - }, array_column(\vtlib\Functions::getAllModules(false, true), 'tabsequence', 'name')); - $excludedModules = ['SMSNotifier', 'ModComments']; + $allModules = array_map(fn ($v) => 0 > $v ? 999 : sprintf('%03d', $v), array_column(\vtlib\Functions::getAllModules(false, true), 'tabsequence', 'name')); + $excludedModules = ['ModComments']; $baseModules = $return = $modules = $baseModules = []; foreach (array_keys(\App\ModuleHierarchy::getModulesByLevel(0)) as $moduleName) { if (\App\Module::isModuleActive($moduleName)) {
app/Condition.php+49 −12 modified@@ -5,8 +5,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> @@ -20,7 +20,7 @@ class Condition { /** - * Data filter list. + * @var array Data filter list. */ const DATE_OPERATORS = [ 'custom' => ['label' => 'LBL_CUSTOM'], @@ -57,8 +57,14 @@ class Condition 'next120days' => ['label' => 'LBL_NEXT_120_DAYS'], 'moreThanDaysAgo' => ['label' => 'LBL_DATE_CONDITION_MORE_THAN_DAYS_AGO'], ]; + /** - * Supported advanced filter operations. + * @var string[] List of field comparison operators + */ + const FIELD_COMPARISON_OPERATORS = ['ef', 'nf', 'lf', 'gf', 'mf', 'hf']; + + /** + * @var string[] Supported advanced filter operations. */ const STANDARD_OPERATORS = [ 'e' => 'LBL_EQUALS', @@ -81,19 +87,27 @@ class Condition 'om' => 'LBL_CURRENTLY_LOGGED_USER', 'nom' => 'LBL_USER_CURRENTLY_NOT_LOGGED', 'ogr' => 'LBL_CURRENTLY_LOGGED_USER_GROUP', + 'ogu' => 'LBL_USERS_GROUP_LOGGED_IN_USER', 'wr' => 'LBL_IS_WATCHING_RECORD', 'nwr' => 'LBL_IS_NOT_WATCHING_RECORD', 'hs' => 'LBL_HAS_CHANGED', 'hst' => 'LBL_HAS_CHANGED_TO', 'ro' => 'LBL_IS_RECORD_OPEN', 'rc' => 'LBL_IS_RECORD_CLOSED', 'nco' => 'LBL_NOT_CREATED_BY_OWNER', + 'ef' => 'LBL_EQUALS_FIELD', + 'nf' => 'LBL_NOT_EQUAL_TO_FIELD', + 'lf' => 'LBL_LESS_THAN_FIELD', + 'gf' => 'LBL_GREATER_THAN_FIELD', + 'mf' => 'LBL_LESS_THAN_OR_EQUAL_FIELD', + 'hf' => 'LBL_GREATER_OR_EQUAL_FIELD', ]; + /** - * Operators without values. + * @var string[] Operators without values. */ const OPERATORS_WITHOUT_VALUES = [ - 'y', 'ny', 'om', 'nom', 'ogr', 'wr', 'nwr', 'hs', 'ro', 'rc', 'nco', + 'y', 'ny', 'om', 'nom', 'ogr', 'wr', 'nwr', 'hs', 'ro', 'rc', 'nco', 'ogu', 'smallerthannow', 'greaterthannow', 'prevfy', @@ -168,14 +182,15 @@ public static function validSearchParams(string $moduleName, array $searchParams if (!isset($fields[$referenceField], $relatedFields[$relatedFieldName])) { throw new Exceptions\IllegalValue("ERR_FIELD_NOT_FOUND||{$param[0]}||" . Utils::varExport($param, true), 406); } - $fieldModel = $relatedFields[$relatedFieldName]; + $value = $relatedFields[$relatedFieldName]->getUITypeModel()->getDbConditionBuilderValue($param[2], $param[1]); + } elseif (0 === strpos($param[0], 'relationColumn_') && preg_match('/(^relationColumn_)(\d+)$/', $param[0])) { + $value = (int) $param[2]; } else { if (!isset($fields[$param[0]])) { throw new Exceptions\IllegalValue("ERR_FIELD_NOT_FOUND||{$param[0]}||" . Utils::varExport($param, true), 406); } - $fieldModel = $fields[$param[0]]; + $value = $fields[$param[0]]->getUITypeModel()->getDbConditionBuilderValue($param[2], $param[1]); } - $value = $fieldModel->getUITypeModel()->getDbConditionBuilderValue($param[2], $param[1]); if ($convert) { $param[2] = $value; } @@ -220,7 +235,7 @@ public static function getConditionsFromRequest(array $conditions): array } else { $operator = $condition['operator']; $value = $condition['value'] ?? ''; - if (!\in_array($operator, self::OPERATORS_WITHOUT_VALUES + array_keys(self::DATE_OPERATORS))) { + if (!\in_array($operator, array_merge(self::OPERATORS_WITHOUT_VALUES, self::FIELD_COMPARISON_OPERATORS, array_keys(self::DATE_OPERATORS)))) { [$fieldName, $fieldModuleName,] = array_pad(explode(':', $condition['fieldname']), 3, false); $value = \Vtiger_Module_Model::getInstance($fieldModuleName)->getFieldByName($fieldName) ->getUITypeModel() @@ -291,7 +306,7 @@ private static function parseConditions(?array $conditions, \Vtiger_Record_Model public static function checkCondition(array $rule, \Vtiger_Record_Model $recordModel): bool { [$fieldName, $moduleName, $sourceFieldName] = array_pad(explode(':', $rule['fieldname']), 3, false); - if (!empty($sourceFieldName)) { + if ($sourceFieldName) { if ($recordModel->isEmpty($sourceFieldName)) { return false; } @@ -331,7 +346,7 @@ public static function getFieldsFromConditions(array $conditions): array if (isset($conditions['rules'])) { foreach ($conditions['rules'] as &$condition) { if (isset($condition['condition'])) { - $condition = static::getFieldsFromConditions($condition); + $fields = array_merge_recursive($fields, static::getFieldsFromConditions($condition)); } else { [$fieldName, $moduleName, $sourceFieldName] = array_pad(explode(':', $condition['fieldname']), 3, false); if ($sourceFieldName) { @@ -377,4 +392,26 @@ public static function removeFieldFromCondition(string $baseModuleName, array $c } return $conditions; } + + /** + * Checks structure advancedConditions. + * + * @param array $advancedConditions + * + * @return array + */ + public static function validAdvancedConditions(array $advancedConditions): array + { + if (!empty($advancedConditions['relationConditions']) && 0 != $advancedConditions['relationId']) { + $advancedConditions['relationConditions'] = self::getConditionsFromRequest($advancedConditions['relationConditions']); + } + if (!empty($advancedConditions['relationColumns'])) { + array_map(function ($v) { + if (!\App\Validator::integer($v)) { + throw new \App\Exceptions\IllegalValue('ERR_NOT_ALLOWED_VALUE||' . $v, 406); + } + }, $advancedConditions['relationColumns']); + } + return $advancedConditions; + } }
app/Conditions/QueryFields/AccountNameField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/QueryFields/AdvPercentageField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/QueryFields/BarcodeField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Adrian Kon <a.kon@yetiforce.com> */
app/Conditions/QueryFields/BaseField.php+83 −22 modified@@ -1,11 +1,11 @@ <?php /** - * Base Query Field file. + * Base query field conditions file. * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -15,12 +15,12 @@ use App\Log; /** - * Base Query Field Class. + * Base query field conditions class. */ class BaseField { /** - * @var QueryGenerator + * @var \App\QueryGenerator */ protected $queryGenerator; @@ -73,7 +73,7 @@ public function __construct(\App\QueryGenerator $queryGenerator, $fieldModel = f * * @return string */ - public function getModuleName() + public function getModuleName(): string { return $this->queryGenerator->getModule(); } @@ -83,7 +83,7 @@ public function getModuleName() * * @param string $operator */ - public function setOperator($operator) + public function setOperator(string $operator): void { $this->operator = strtolower($operator); } @@ -93,7 +93,7 @@ public function setOperator($operator) * * @param array $relatedInfo */ - public function setRelated($relatedInfo) + public function setRelated(array $relatedInfo): void { $this->related = $relatedInfo; } @@ -125,7 +125,7 @@ public function getListViewFields() * * @return array */ - public function getOrderBy($order = false) + public function getOrderBy($order = false): array { $order = $order && \App\Db::DESC === strtoupper($order) ? SORT_DESC : SORT_ASC; return [$this->getColumnName() => $order]; @@ -136,20 +136,42 @@ public function getOrderBy($order = false) * * @return string */ - public function getColumnName() + public function getColumnName(): string { if ($this->fullColumnName) { return $this->fullColumnName; } return $this->fullColumnName = $this->getTableName() . '.' . $this->fieldModel->getColumnName(); } + /** + * Get column name from source. + * + * @return string + */ + public function getColumnNameFromSource(): string + { + [$fieldName, $fieldModuleName, $sourceFieldName] = array_pad(explode(':', $this->value), 3, ''); + if ($sourceFieldName) { + $fieldModel = $this->queryGenerator->getRelatedModuleField($fieldName, $fieldModuleName); + $this->queryGenerator->addRelatedJoin([ + 'sourceField' => $sourceFieldName, + 'relatedModule' => $fieldModuleName, + 'relatedField' => $fieldName, + ]); + } else { + $fieldModel = $this->queryGenerator->getModuleField($fieldName); + $this->queryGenerator->addTableToQuery($fieldModel->getTableName()); + } + return $fieldModel ? ($fieldModel->getTableName() . $sourceFieldName . '.' . $fieldModel->getColumnName()) : ''; + } + /** * Get table name. * * @return string */ - public function getTableName() + public function getTableName(): string { if ($this->tableName) { return $this->tableName; @@ -166,7 +188,7 @@ public function getTableName() * * @param string $tableName */ - public function setTableName($tableName) + public function setTableName($tableName): void { $this->tableName = $tableName; } @@ -194,7 +216,7 @@ public function getCondition(?string $operator = null) * * @return array */ - public function operatorA() + public function operatorA(): array { return $this->getCondition($this->getOperator()); } @@ -205,7 +227,7 @@ public function operatorA() * * @return array */ - public function operatorWca() + public function operatorWca(): array { return ['like', $this->getColumnName(), str_replace('*', '%', "%{$this->getValue()}%"), false]; } @@ -230,7 +252,6 @@ public function getValue() public function setValue($value) { $this->value = $value; - return $this; } @@ -239,7 +260,7 @@ public function setValue($value) * * @return array */ - public function operatorC() + public function operatorC(): array { return ['like', $this->getColumnName(), $this->getValue()]; } @@ -249,7 +270,7 @@ public function operatorC() * * @return array */ - public function operatorE() + public function operatorE(): array { return [$this->getColumnName() => $this->getValue()]; } @@ -259,18 +280,38 @@ public function operatorE() * * @return array */ - public function operatorN() + public function operatorN(): array { $value = $this->getValue(); return [(\is_array($value) ? 'not in' : '<>'), $this->getColumnName(), $value]; } + /** + * Starts with operator. + * + * @return array + */ + public function operatorS() + { + return ['like', $this->getColumnName(), $this->getValue() . '%', false]; + } + + /** + * Ends with operator. + * + * @return array + */ + public function operatorEw() + { + return ['like', $this->getColumnName(), '%' . $this->getValue(), false]; + } + /** * Is empty operator. * * @return array */ - public function operatorY() + public function operatorY(): array { return ['or', [$this->getColumnName() => null], @@ -283,7 +324,7 @@ public function operatorY() * * @return array */ - public function operatorNy() + public function operatorNy(): array { return ['and', ['not', [$this->getColumnName() => null]], @@ -296,11 +337,31 @@ public function operatorNy() * * @return array */ - public function operatorK() + public function operatorK(): array { return ['not like', $this->getColumnName(), $this->getValue()]; } + /** + * Is equal to selected field operator. + * + * @return array + */ + public function operatorEf(): array + { + return [$this->getColumnName() => new \yii\db\Expression($this->getColumnNameFromSource())]; + } + + /** + * Is not equal to selected field operator. + * + * @return array + */ + public function operatorNf(): array + { + return ['<>', $this->getColumnName(), new \yii\db\Expression($this->getColumnNameFromSource())]; + } + /** * Get field model. * @@ -325,7 +386,7 @@ public function __clone() * * @return string */ - public function getOperator() + public function getOperator(): string { $operator = $this->operator; if ('a' === $this->operator) {
app/Conditions/QueryFields/BooleanField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class BooleanField extends BaseField
app/Conditions/QueryFields/CategoryMultipicklistField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Arkadiusz Dudek <a.dudek@yetiforce.com>
app/Conditions/QueryFields/ChangesJsonField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/QueryFields/CountryField.php+4 −4 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -21,7 +21,7 @@ class CountryField extends BaseField * * @return array */ - public function operatorN() + public function operatorN(): array { return ['NOT IN', $this->getColumnName(), $this->getValue()]; } @@ -37,7 +37,7 @@ public function getValue() } /** {@inheritdoc} */ - public function getOperator() + public function getOperator(): string { return 'a' === $this->operator ? 'e' : $this->operator; }
app/Conditions/QueryFields/CurrencyField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class CurrencyField extends IntegerField
app/Conditions/QueryFields/CurrencyInventoryField.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Adrian Koń <a.kon@yetiforce.com> */
app/Conditions/QueryFields/CurrencyListField.php+4 −3 modified@@ -7,10 +7,11 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class CurrencyListField extends PicklistField { @@ -21,7 +22,7 @@ class CurrencyListField extends PicklistField * * @return array */ - public function getOrderBy($order = false) + public function getOrderBy($order = false): array { $this->queryGenerator->addJoin(['LEFT JOIN', 'vtiger_currency_info', $this->getColumnName() . ' = vtiger_currency_info.id']); if ($order && 'desc' === strtolower($order)) {
app/Conditions/QueryFields/DateField.php+14 −24 modified@@ -1,30 +1,32 @@ <?php - /** - * Date Query Field file. + * Date query field conditions file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ namespace App\Conditions\QueryFields; /** - * Date Query Field Class. - * - * @package UIType - * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) - * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * Date query field conditions class. */ class DateField extends BaseField { + use \App\Conditions\QueryTraits\Comparison; + use \App\Conditions\QueryTraits\ComparisonField; + /** * Get order by. * * @param mixed $order * * @return array */ - public function getOrderBy($order = false) + public function getOrderBy($order = false): array { if ($order && 'DESC' === strtoupper($order)) { $sort = SORT_DESC; @@ -102,7 +104,6 @@ public function getStdValue() public function getStdOperator() { $value = $this->getStdValue(); - return ['between', $this->getColumnName(), $value[0], $value[1]]; } @@ -114,8 +115,7 @@ public function getStdOperator() public function operatorBw() { $value = $this->getArrayValue(); - - return ['between', $this->getColumnName(), $value[0], $value[1]]; + return ['between', $this->getColumnName(), $value[0], $value[1] ?? $value[0]]; } /** @@ -133,7 +133,7 @@ public function operatorB() * * @return array */ - public function operatorA() + public function operatorA(): array { return ['>', $this->getColumnName(), $this->getValue()]; } @@ -179,14 +179,4 @@ public function operatorMoreThanDaysAgo() { return ['<=', $this->getColumnName(), date('Y-m-d', strtotime('-' . $this->getValue() . ' days'))]; } - - /** - * Lower operator. - * - * @return array - */ - public function operatorL() - { - return ['<', $this->getColumnName(), $this->getValue()]; - } }
app/Conditions/QueryFields/DatetimeField.php+5 −5 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -40,7 +40,7 @@ public function getArrayValue() * * @return array */ - public function operatorE() + public function operatorE(): array { $value = $this->getValue(); @@ -52,7 +52,7 @@ public function operatorE() * * @return array */ - public function operatorN() + public function operatorN(): array { $value = $this->getValue(); @@ -86,7 +86,7 @@ public function operatorB() * * @return array */ - public function operatorA() + public function operatorA(): array { return ['>', $this->getColumnName(), $this->getValue() . ' 23:59:59']; }
app/Conditions/QueryFields/DocumentsFileUploadField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class DocumentsFileUploadField extends StringField
app/Conditions/QueryFields/DoubleField.php+30 −2 modified@@ -7,10 +7,38 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> + * @author Adrian Kon <a.kon@yetiforce.com> */ class DoubleField extends IntegerField { + /** + * Auto operator, it allows you to use formulas: >10 <40, >1, <7. + * + * @return array + */ + public function operatorA(): array + { + $value = \App\Purifier::decodeHtml($this->value); + $condition = ['and']; + $conditionFound = false; + $explodeBySpace = explode(' ', $value); + foreach ($explodeBySpace as $valueToCondition) { + $operatorWasFound = false; + foreach (static::$extendedOperators as $exo) { + if (false !== strpos($valueToCondition, $exo) && false === $operatorWasFound) { + $ev = explode($exo, $valueToCondition); + $condition[] = [$exo, $this->getColumnName(), $ev[1]]; + $conditionFound = true; + $operatorWasFound = true; + } + } + } + if (!$conditionFound) { + return parent::operatorE(); + } + return $condition; + } }
app/Conditions/QueryFields/EmailField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class EmailField extends StringField
app/Conditions/QueryFields/FileLocationTypeField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class FileLocationTypeField extends PicklistField
app/Conditions/QueryFields/IbanField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Adrian Kon <a.kon@yetiforce.com> */
app/Conditions/QueryFields/IdField.php+4 −4 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class IdField extends StringField @@ -28,7 +28,7 @@ public function operatorS() * * @return string */ - public function getColumnName() + public function getColumnName(): string { if ($this->fullColumnName) { return $this->fullColumnName; @@ -51,7 +51,7 @@ public function operatorEw() * * @return array */ - public function operatorA() + public function operatorA(): array { return ['>', $this->getColumnName(), $this->getValue()]; }
app/Conditions/QueryFields/ImageField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class ImageField extends MultiImageField
app/Conditions/QueryFields/IntegerField.php+21 −51 modified@@ -1,26 +1,36 @@ <?php - -namespace App\Conditions\QueryFields; - /** - * Integer Query Field Class. + * Integer query field conditions file. * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\QueryFields; + +/** + * Integer query field conditions class. */ class IntegerField extends BaseField { + use \App\Conditions\QueryTraits\Comparison; + use \App\Conditions\QueryTraits\ComparisonField; + + /** + * @var string[] List of extended operators + */ public static $extendedOperators = ['>=', '<=', '<', '>']; /** - * Auto operator, it allows you to use formulas: >10<40, >1, <7. + * Auto operator, it allows you to use formulas: >10 <40, >1, <7. * * @return array */ - public function operatorA() + public function operatorA(): array { $value = \App\Purifier::decodeHtml($this->value); $condition = ['and']; @@ -40,57 +50,17 @@ public function operatorA() } /** {@inheritdoc} */ - public function getOperator() + public function getOperator(): string { return 'a' === $this->operator ? 'e' : $this->operator; } - /** - * Lower operator. - * - * @return array - */ - public function operatorL() - { - return ['<', $this->getColumnName(), $this->getValue()]; - } - - /** - * Greater operator. - * - * @return array - */ - public function operatorG() - { - return ['>', $this->getColumnName(), $this->getValue()]; - } - - /** - * Lower or equal operator. - * - * @return array - */ - public function operatorM() - { - return ['<=', $this->getColumnName(), $this->getValue()]; - } - - /** - * Greater or equal operator. - * - * @return array - */ - public function operatorH() - { - return ['>=', $this->getColumnName(), $this->getValue()]; - } - /** * Is empty operator. * * @return array */ - public function operatorY() + public function operatorY(): array { return [$this->getColumnName() => null]; } @@ -100,7 +70,7 @@ public function operatorY() * * @return array */ - public function operatorNy() + public function operatorNy(): array { return ['not', [$this->getColumnName() => null]]; }
app/Conditions/QueryFields/InventoryLimitField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class InventoryLimitField extends PicklistField
app/Conditions/QueryFields/LanguagesField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class LanguagesField extends PicklistField
app/Conditions/QueryFields/MagentoServerField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/QueryFields/MailScannerActionsField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Dudek <a.dudek@yetiforce.com> */
app/Conditions/QueryFields/MailScannerFieldsField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Dudek <a.dudek@yetiforce.com> */
app/Conditions/QueryFields/MeetingUrlField.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/QueryFields/ModulesField.php+4 −3 modified@@ -7,9 +7,10 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ModulesField extends BaseField { @@ -18,7 +19,7 @@ class ModulesField extends BaseField * * @return array */ - public function operatorN() + public function operatorN(): array { return ['NOT IN', $this->getColumnName(), $this->getValue()]; }
app/Conditions/QueryFields/MultiAttachmentField.php+36 −0 added@@ -0,0 +1,36 @@ +<?php +/** + * MultiAttachment Query Field File. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + */ + +namespace App\Conditions\QueryFields; + +/** + * MultiAttachment Query Field Class. + */ +class MultiAttachmentField extends BaseField +{ + /** {@inheritdoc} */ + public function operatorY(): array + { + return ['or', + [$this->getColumnName() => null], + ['=', $this->getColumnName(), ''], + ]; + } + + /** {@inheritdoc} */ + public function operatorNy(): array + { + return ['and', + ['not', [$this->getColumnName() => null]], + ['<>', $this->getColumnName(), ''], + ]; + } +}
app/Conditions/QueryFields/MultiCurrencyField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/QueryFields/MultiDependFieldField.php+19 −0 added@@ -0,0 +1,19 @@ +<?php +/** + * Multi depend query field file. + * + * @package App + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\QueryFields; + +/** + * Multi depend query field class. + */ +class MultiDependFieldField extends BaseField +{ +}
app/Conditions/QueryFields/MultiDomainField.php+4 −3 modified@@ -4,9 +4,10 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Adrian Kon <a.kon@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ namespace App\Conditions\QueryFields; @@ -23,7 +24,7 @@ public function getValue() } /** {@inheritdoc} */ - public function getOperator() + public function getOperator(): string { return 'a' === $this->operator ? 'c' : $this->operator; }
app/Conditions/QueryFields/MultiEmailField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> */
app/Conditions/QueryFields/MultiImageField.php+4 −4 modified@@ -7,14 +7,14 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class MultiImageField extends BaseField { /** {@inheritdoc} */ - public function operatorY() + public function operatorY(): array { return ['or', [$this->getColumnName() => null], @@ -23,7 +23,7 @@ public function operatorY() } /** {@inheritdoc} */ - public function operatorNy() + public function operatorNy(): array { return ['and', ['not', [$this->getColumnName() => null]],
app/Conditions/QueryFields/MultiListFieldsField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Dudek <a.dudek@yetiforce.com> */
app/Conditions/QueryFields/MultiownerField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */
app/Conditions/QueryFields/MultipicklistField.php+7 −10 modified@@ -7,18 +7,15 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class MultipicklistField extends BaseField { - /** - * Separator. - * - * @var string - */ + /** @var string Separator. */ protected $separator = ' |##| '; /** @@ -70,7 +67,7 @@ public function getValue() * * @return array */ - public function operatorN() + public function operatorN(): array { return ['not', [$this->getColumnName() => $this->getValue()]]; } @@ -80,7 +77,7 @@ public function operatorN() * * @return array */ - public function operatorC() + public function operatorC(): array { $condition = ['or']; foreach ($this->getValue() as $value) { @@ -100,7 +97,7 @@ public function operatorC() * * @return array */ - public function operatorK() + public function operatorK(): array { $condition = ['and']; foreach ($this->getValue() as $value) {
app/Conditions/QueryFields/MultiReferenceField.php+4 −3 modified@@ -4,9 +4,10 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ namespace App\Conditions\QueryFields; @@ -24,7 +25,7 @@ class MultiReferenceField extends MultipicklistField protected $separator = ','; /** {@inheritdoc} */ - public function getOperator() + public function getOperator(): string { return 'a' === $this->operator ? 'c' : $this->operator; }
app/Conditions/QueryFields/MultiReferenceValueField.php+6 −5 modified@@ -7,9 +7,10 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class MultiReferenceValueField extends BaseField { @@ -18,7 +19,7 @@ class MultiReferenceValueField extends BaseField * * @return array */ - public function operatorE() + public function operatorE(): array { return ['or like', $this->getColumnName(), $this->getValue()]; } @@ -37,7 +38,7 @@ public function getValue() * * @return array */ - public function operatorN() + public function operatorN(): array { return ['or not like', $this->getColumnName(), $this->getValue()]; } @@ -47,7 +48,7 @@ public function operatorN() * * @return array */ - public function operatorC() + public function operatorC(): array { $condition = ['or']; foreach ($this->getValue() as $value) {
app/Conditions/QueryFields/OwnerField.php+26 −7 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -19,7 +19,7 @@ class OwnerField extends BaseField * * @return array */ - public function operatorE() + public function operatorE(): array { if (!\is_array($this->value)) { $this->value = explode('##', $this->value); @@ -36,7 +36,7 @@ public function operatorE() * * @return array */ - public function operatorN() + public function operatorN(): array { if (!\is_array($this->value)) { $this->value = explode('##', $this->value); @@ -99,6 +99,25 @@ public function operatorOgr(): array return [$this->getColumnName() => \array_keys($groups)]; } + /** + * Users who belong to the same group as the currently logged in user. + * + * @return array + */ + public function operatorOgu(): array + { + $groups = \App\Fields\Owner::getInstance($this->getModuleName())->getGroups(false, 'private'); + if ($groups) { + $condition = ['or']; + foreach (array_keys($groups) as $idGroup) { + $condition[] = [$this->getColumnName() => (new \App\Db\Query())->select(['userid'])->from(["condition_groups_{$idGroup}_" . \App\Layout::getUniqueId() => \App\PrivilegeUtil::getQueryToUsersByGroup((int) $idGroup)])]; + } + } else { + $condition = [$this->getColumnName() => (new \yii\db\Expression('0=1'))]; + } + return $condition; + } + /** * Watched record. * @@ -146,7 +165,7 @@ public function operatorNwr() * * @return array */ - public function getOrderBy($order = false) + public function getOrderBy($order = false): array { $this->queryGenerator->addJoin(['LEFT JOIN', 'vtiger_users', 'vtiger_users.id = ' . $this->getColumnName()]); $this->queryGenerator->addJoin(['LEFT JOIN', 'vtiger_groups', 'vtiger_groups.groupid = ' . $this->getColumnName()]); @@ -161,7 +180,7 @@ public function getOrderBy($order = false) * * @return array */ - public function operatorNy() + public function operatorNy(): array { return ['and', ['not', [$this->getColumnName() => null]], @@ -174,7 +193,7 @@ public function operatorNy() * * @return array */ - public function operatorY() + public function operatorY(): array { return ['or', [$this->getColumnName() => null],
app/Conditions/QueryFields/PasswordField.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Adrian Kon <a.kon@yetiforce.com> */
app/Conditions/QueryFields/PercentageField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class PercentageField extends IntegerField
app/Conditions/QueryFields/PhoneField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class PhoneField extends StringField
app/Conditions/QueryFields/PicklistField.php+3 −3 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class PicklistField extends BaseField @@ -18,7 +18,7 @@ class PicklistField extends BaseField * * @return array */ - public function operatorN() + public function operatorN(): array { return ['NOT IN', $this->getColumnName(), $this->getValue()]; }
app/Conditions/QueryFields/RangeTimeField.php+11 −7 modified@@ -1,16 +1,20 @@ <?php - -namespace App\Conditions\QueryFields; - /** - * RangeTime Query Field Class. + * Range Time query field conditions file. * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) - * @author Tomasz Kur <t.kur@yetiforce.com> + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\QueryFields; + +/** + * Range Time query field conditions class. */ class RangeTimeField extends BaseField { + use \App\Conditions\QueryTraits\ComparisonField; }
app/Conditions/QueryFields/RecordNumberField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class RecordNumberField extends StringField
app/Conditions/QueryFields/RecurrenceField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class RecurrenceField extends BooleanField
app/Conditions/QueryFields/ReferenceExtendField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ReferenceExtendField extends ReferenceField
app/Conditions/QueryFields/ReferenceField.php+12 −12 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -22,9 +22,9 @@ public function getTables() /** * Get related column name. * - * @return string + * @return string[] */ - public function getRelatedTableName() + public function getRelatedTableName(): array { if ($this->related) { if (\App\Config::performance('SEARCH_REFERENCE_BY_AJAX')) { @@ -73,7 +73,7 @@ public function getRelatedTables(array $modules, string $fieldName): array * * @return array */ - public function operatorA() + public function operatorA(): array { if (\App\Config::performance('SEARCH_REFERENCE_BY_AJAX')) { if (false === strpos($this->value, '##')) { @@ -93,7 +93,7 @@ public function operatorA() * * @return array */ - public function operatorE() + public function operatorE(): array { $condition = ['or']; foreach ($this->getRelatedTableName() as $formattedName) { @@ -117,7 +117,7 @@ public function operatorEid() * * @return array */ - public function operatorN() + public function operatorN(): array { $condition = ['or']; foreach ($this->getRelatedTableName() as $formattedName) { @@ -159,7 +159,7 @@ public function operatorEw() * * @return array */ - public function operatorC() + public function operatorC(): array { $condition = ['or']; foreach ($this->getRelatedTableName() as $formattedName) { @@ -173,7 +173,7 @@ public function operatorC() * * @return array */ - public function operatorK() + public function operatorK(): array { $condition = ['or']; foreach ($this->getRelatedTableName() as $formattedName) { @@ -187,7 +187,7 @@ public function operatorK() * * @return array */ - public function operatorY() + public function operatorY(): array { return ['or', [$this->getColumnName() => null], @@ -201,7 +201,7 @@ public function operatorY() * * @return array */ - public function operatorNy() + public function operatorNy(): array { return ['and', ['not', [$this->getColumnName() => null]], @@ -217,7 +217,7 @@ public function operatorNy() * * @return array */ - public function getOrderBy($order = false) + public function getOrderBy($order = false): array { $condition = []; if ($order && 'DESC' === strtoupper($order)) {
app/Conditions/QueryFields/ReferenceLinkField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class ReferenceLinkField extends ReferenceField
app/Conditions/QueryFields/ReferenceProcessField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class ReferenceProcessField extends ReferenceField
app/Conditions/QueryFields/ReferenceSubProcessField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class ReferenceSubProcessField extends ReferenceField
app/Conditions/QueryFields/ReferenceSubProcessSLField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/QueryFields/ReminderField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class ReminderField extends IntegerField
app/Conditions/QueryFields/SalutationField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class SalutationField extends StringField
app/Conditions/QueryFields/ServerAccessField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */
app/Conditions/QueryFields/SharedOwnerField.php+29 −8 modified@@ -7,15 +7,15 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ class SharedOwnerField extends BaseField { /** {@inheritdoc} */ - public function getColumnName() + public function getColumnName(): string { if ($this->fullColumnName) { return $this->fullColumnName; @@ -33,7 +33,7 @@ public function getColumnName() * * @return array */ - public function operatorE() + public function operatorE(): array { if (empty($this->value)) { return []; @@ -46,7 +46,7 @@ public function operatorE() * * @return array */ - public function operatorN() + public function operatorN(): array { if (empty($this->value)) { return []; @@ -76,12 +76,33 @@ public function operatorOgr(): array return $this->operatorE(); } + /** + * Users who belong to the same group as the currently logged in user. + * + * @return array + */ + public function operatorOgu(): array + { + $groups = \App\Fields\Owner::getInstance($this->getModuleName())->getGroups(false, 'private'); + if ($groups) { + $where = ['or']; + $query = (new \App\Db\Query())->select(['crmid'])->from('u_#__crmentity_showners'); + foreach (array_keys($groups) as $groupId) { + $where[] = ['u_#__crmentity_showners.userid' => (new \App\Db\Query())->select(['userid'])->from(["condition_groups_{$groupId}_" . \App\Layout::getUniqueId() => \App\PrivilegeUtil::getQueryToUsersByGroup((int) $groupId)])]; + } + $condition = [$this->getColumnName() => $query->where($where)]; + } else { + $condition = [$this->getColumnName() => (new \yii\db\Expression('0=1'))]; + } + return $condition; + } + /** * Contains operator. * * @return array */ - public function operatorC() + public function operatorC(): array { return $this->operatorE(); } @@ -91,7 +112,7 @@ public function operatorC() * * @return array */ - public function operatorNy() + public function operatorNy(): array { if ($this->related) { $fieldModel = $this->queryGenerator->getModuleField($this->related['sourceField']); @@ -110,7 +131,7 @@ public function operatorNy() * * @return array */ - public function operatorY() + public function operatorY(): array { if ($this->related) { $fieldModel = $this->queryGenerator->getModuleField($this->related['sourceField']);
app/Conditions/QueryFields/SkypeField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author arkadiusz.dudek <a.dudek@yetiforce.com> */ class SkypeField extends StringField
app/Conditions/QueryFields/SmtpField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> */
app/Conditions/QueryFields/StringField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class StringField extends BaseField
app/Conditions/QueryFields/TaxesField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/QueryFields/TextField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class TextField extends StringField
app/Conditions/QueryFields/ThemeField.php+4 −3 modified@@ -7,9 +7,10 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Sławomir Kłos <s.klos@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ThemeField extends BaseField { @@ -18,7 +19,7 @@ class ThemeField extends BaseField * * @return array */ - public function operatorN() + public function operatorN(): array { return ['NOT IN', $this->getColumnName(), $this->getValue()]; }
app/Conditions/QueryFields/TimeField.php+13 −7 modified@@ -1,18 +1,24 @@ <?php - -namespace App\Conditions\QueryFields; - /** - * Time Query Field Class. + * Time query field conditions file. * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\QueryFields; + +/** + * Time query field conditions class. */ class TimeField extends BaseField { + use \App\Conditions\QueryTraits\ComparisonField; + /** * Before operator. * @@ -28,7 +34,7 @@ public function operatorB() * * @return array */ - public function operatorA() + public function operatorA(): array { return ['>', $this->getColumnName(), $this->getValue()]; }
app/Conditions/QueryFields/TokenField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/QueryFields/TotalTimeField.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/QueryFields/TreeField.php+3 −3 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class TreeField extends StringField @@ -47,7 +47,7 @@ public function getValue() * * @return array */ - public function getOrderBy($order = false) + public function getOrderBy($order = false): array { $this->queryGenerator->addJoin(['LEFT JOIN', 'vtiger_trees_templates_data', $this->getColumnName() . ' = vtiger_trees_templates_data.tree AND vtiger_trees_templates_data.templateid = :template', [':template' => $this->fieldModel->getFieldParams()]]); if ($order && 'DESC' === strtoupper($order)) {
app/Conditions/QueryFields/TwitterField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Arkadiusz Adach <a.adach@yetiforce.com> */
app/Conditions/QueryFields/UrlField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> */ class UrlField extends StringField
app/Conditions/QueryFields/UserCreatorField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/QueryFields/UserReferenceField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Sławomir Kłos <s.klos@yetiforce.com> */ class UserReferenceField extends OwnerField
app/Conditions/QueryFields/UserRoleField.php+6 −5 modified@@ -7,9 +7,10 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class UserRoleField extends StringField { @@ -18,7 +19,7 @@ class UserRoleField extends StringField * * @return array */ - public function operatorE() + public function operatorE(): array { $this->queryGenerator->addJoin(['INNER JOIN', 'vtiger_user2role', 'vtiger_user2role.userid = vtiger_users.id']); @@ -30,7 +31,7 @@ public function operatorE() * * @return array */ - public function operatorC() + public function operatorC(): array { $this->queryGenerator->addJoin(['INNER JOIN', 'vtiger_user2role', 'vtiger_user2role.userid = vtiger_users.id']); $this->queryGenerator->addJoin(['INNER JOIN', 'vtiger_role', 'vtiger_role.roleid = ' . $this->getColumnName()]); @@ -45,7 +46,7 @@ public function operatorC() * * @return array */ - public function getOrderBy($order = false) + public function getOrderBy($order = false): array { $this->queryGenerator->addJoin(['INNER JOIN', 'vtiger_user2role', 'vtiger_user2role.userid = vtiger_users.id']); $this->queryGenerator->addJoin(['INNER JOIN', 'vtiger_role', 'vtiger_role.roleid = ' . $this->getColumnName()]);
app/Conditions/QueryTraits/ComparisonField.php+58 −0 added@@ -0,0 +1,58 @@ +<?php +/** + * Query comparison field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\QueryTraits; + +/** + * Query comparison field class. + */ +trait ComparisonField +{ + /** + * Less than field operator. + * + * @return array + */ + public function operatorLf(): array + { + return ['<', $this->getColumnName(), new \yii\db\Expression($this->getColumnNameFromSource())]; + } + + /** + * Greater than field operator. + * + * @return array + */ + public function operatorGf(): array + { + return ['>', $this->getColumnName(), new \yii\db\Expression($this->getColumnNameFromSource())]; + } + + /** + * Less than field or equal operator. + * + * @return array + */ + public function operatorMf(): array + { + return ['<=', $this->getColumnName(), new \yii\db\Expression($this->getColumnNameFromSource())]; + } + + /** + * Greater than field or equal operator. + * + * @return array + */ + public function operatorHf(): array + { + return ['>=', $this->getColumnName(), new \yii\db\Expression($this->getColumnNameFromSource())]; + } +}
app/Conditions/QueryTraits/Comparison.php+58 −0 added@@ -0,0 +1,58 @@ +<?php +/** + * Query comparison file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\QueryTraits; + +/** + * Query comparison class. + */ +trait Comparison +{ + /** + * Lower operator. + * + * @return array + */ + public function operatorL(): array + { + return ['<', $this->getColumnName(), $this->getValue()]; + } + + /** + * Greater operator. + * + * @return array + */ + public function operatorG(): array + { + return ['>', $this->getColumnName(), $this->getValue()]; + } + + /** + * Lower or equal operator. + * + * @return array + */ + public function operatorM(): array + { + return ['<=', $this->getColumnName(), $this->getValue()]; + } + + /** + * Greater or equal operator. + * + * @return array + */ + public function operatorH(): array + { + return ['>=', $this->getColumnName(), $this->getValue()]; + } +}
app/Conditions/RecordFields/AccountNameField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/AdvPercentageField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/BarcodeField.php+19 −0 added@@ -0,0 +1,19 @@ +<?php +/** + * Barcode query condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Barcode query condition record field class. + */ +class BarcodeField extends BaseField +{ +}
app/Conditions/RecordFields/BaseField.php+65 −57 modified@@ -4,9 +4,10 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace App\Conditions\RecordFields; @@ -98,6 +99,23 @@ public function getValue() return $this->recordModel->get($this->fieldModel->getName()); } + /** + * Get value from record source. + * + * @return string + */ + public function getValueFromSource(): string + { + $return = ''; + [$fieldName, $fieldModuleName, $sourceFieldName] = array_pad(explode(':', $this->value), 3, ''); + if ($sourceFieldName && ($relId = $this->recordModel->get($sourceFieldName)) && \App\Record::isExists($relId, $fieldModuleName)) { + $return = \Vtiger_Record_Model::getInstanceById($relId, $fieldModuleName)->get($fieldName); + } elseif (!$sourceFieldName && $this->recordModel->getModuleName() === $fieldModuleName) { + $return = $this->recordModel->get($fieldName); + } + return $return; + } + /** * Equals operator. * @@ -165,60 +183,20 @@ public function operatorC() * * @return bool */ - public function operatorK() + public function operatorK(): bool { if (\is_array($this->getValue())) { return !\in_array($this->value, $this->getValue()); } return false === strpos($this->getValue(), $this->value); } - /** - * Less than operator. - * - * @return bool - */ - public function operatorL() - { - return $this->getValue() < $this->value; - } - - /** - * Greater than operator. - * - * @return bool - */ - public function operatorG() - { - return $this->getValue() > $this->value; - } - - /** - * Less than or equal to operator. - * - * @return bool - */ - public function operatorM() - { - return $this->getValue() <= $this->value; - } - - /** - * Greater than or equal to operator. - * - * @return bool - */ - public function operatorH() - { - return $this->getValue() >= $this->value; - } - /** * Before operator. * * @return bool */ - public function operatorB() + public function operatorB(): bool { if (empty($this->getValue())) { return false; @@ -234,7 +212,7 @@ public function operatorB() * * @return bool */ - public function operatorA() + public function operatorA(): bool { if (empty($this->getValue())) { return false; @@ -248,29 +226,29 @@ public function operatorA() /** * Is empty operator. * - * @return array + * @return bool */ - public function operatorY() + public function operatorY(): bool { return empty($this->getValue()); } /** * Is not empty operator. * - * @return array + * @return bool */ - public function operatorNy() + public function operatorNy(): bool { return !empty($this->getValue()); } /** * Has changed operator. * - * @return array + * @return bool */ - public function operatorHs() + public function operatorHs(): bool { $hasChanged = $this->recordModel->getPreviousValue($this->fieldModel->getName()); if (false === $hasChanged) { @@ -282,30 +260,60 @@ public function operatorHs() /** * Has changed to operator. * - * @return array + * @return bool */ - public function operatorHst() + public function operatorHst(): bool { return false !== $this->recordModel->getPreviousValue($this->fieldModel->getName()) && $this->getValue() == $this->value; } /** * Is currently logged user operator. * - * @return array + * @return bool */ - public function operatorOm() + public function operatorOm(): bool { return $this->getValue() == \App\User::getCurrentUserId(); } /** - * Is currently logged user group operator. + * Not currently logged user operator. * * @return array */ - public function operatorOgr() + public function operatorNom() + { + return $this->getValue() != \App\User::getCurrentUserId(); + } + + /** + * Is currently logged user group operator. + * + * @return bool + */ + public function operatorOgr(): bool { return \in_array($this->getValue(), \App\User::getCurrentUserModel()->getGroups()); } + + /** + * Is equal to selected field operator. + * + * @return bool + */ + public function operatorEf(): bool + { + return $this->getValue() == $this->getValueFromSource(); + } + + /** + * Is not equal to selected field operator. + * + * @return bool + */ + public function operatorNf(): bool + { + return $this->getValue() != $this->getValueFromSource(); + } }
app/Conditions/RecordFields/BooleanField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class BooleanField extends BaseField
app/Conditions/RecordFields/CategoryMultipicklistField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class CategoryMultipicklistField extends BaseField
app/Conditions/RecordFields/ChangesJsonField.php+19 −0 added@@ -0,0 +1,19 @@ +<?php +/** + * Changes json condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Changes json condition record field class. + */ +class ChangesJsonField extends BaseField +{ +}
app/Conditions/RecordFields/CountryField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/CurrencyField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class CurrencyField extends IntegerField
app/Conditions/RecordFields/CurrencyInventoryField.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/CurrencyListField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class CurrencyListField extends PicklistField
app/Conditions/RecordFields/DateField.php+53 −2 modified@@ -5,8 +5,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -19,10 +19,16 @@ */ class DateField extends BaseField { + use \App\Conditions\RecordTraits\Comparison; + use \App\Conditions\RecordTraits\ComparisonField; + /** {@inheritdoc} */ public function check() { $fn = 'operator' . ucfirst($this->operator); + if (isset(\App\Condition::DATE_OPERATORS[$this->operator]) && !method_exists($this, $fn)) { + $fn = 'getStdOperator'; + } if (method_exists($this, $fn)) { Log::trace("Entering to $fn in " . __CLASS__); return $this->{$fn}(); @@ -373,4 +379,49 @@ public function operatorMoreThanDaysAgo() { return $this->getValue() <= date('Y-m-d', strtotime('-' . $this->value . ' days')); } + + /** + * Between operator. + * + * @return array + */ + public function operatorBw() + { + return $this->operatorCustom(); + } + + /** + * Greater operator. + * + * @return array + */ + public function operatorGreaterthannow() + { + return $this->operatorGreater(); + } + + /** + * Smaller operator. + * + * @return array + */ + public function operatorSmallerthannow() + { + return $this->operatorSmaller(); + } + + /** + * Get value. + * + * @return mixed + */ + public function getStdOperator() + { + $dateValue = date('Y-m-d', strtotime($this->getValue())); + $value = \DateTimeRange::getDateRangeByType($this->operator); + if ($value[0] === $value[1]) { + return $dateValue <= $value[0]; + } + return ($dateValue >= $value[0]) && ($dateValue <= $value[1]); + } }
app/Conditions/RecordFields/DatetimeField.php+33 −2 modified@@ -7,10 +7,41 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class DatetimeField extends DateField { + /** + * Custom operator. + * + * @return bool + */ + public function operatorCustom() + { + [$startDate, $endDate] = explode(',', $this->value); + $dateValue = strtotime($this->getValue()); + return ($dateValue >= strtotime($startDate)) && ($dateValue <= strtotime($endDate)); + } + + /** + * Smaller operator. + * + * @return bool + */ + public function operatorSmaller() + { + return strtotime($this->getValue()) < strtotime('now'); + } + + /** + * Greater operator. + * + * @return bool + */ + public function operatorGreater() + { + return strtotime($this->getValue()) > strtotime('now'); + } }
app/Conditions/RecordFields/DocumentsFileUploadField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class DocumentsFileUploadField extends StringField
app/Conditions/RecordFields/DoubleField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class DoubleField extends IntegerField
app/Conditions/RecordFields/EmailField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class EmailField extends StringField
app/Conditions/RecordFields/FileLocationTypeField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class FileLocationTypeField extends PicklistField
app/Conditions/RecordFields/IbanField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Adrian Kon <a.kon@yetiforce.com> */
app/Conditions/RecordFields/IdField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class IdField extends StringField
app/Conditions/RecordFields/ImageField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ImageField extends MultiImageField
app/Conditions/RecordFields/IntegerField.php+4 −2 modified@@ -7,10 +7,12 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class IntegerField extends BaseField { + use \App\Conditions\RecordTraits\Comparison; + use \App\Conditions\RecordTraits\ComparisonField; }
app/Conditions/RecordFields/InventoryLimitField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class InventoryLimitField extends PicklistField
app/Conditions/RecordFields/LanguagesField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class LanguagesField extends PicklistField
app/Conditions/RecordFields/MagentoServerField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/MailScannerActionsField.php+21 −0 added@@ -0,0 +1,21 @@ +<?php +/** + * Mail scanner actions condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Mail scanner actions condition record field class. + */ +class MailScannerActionsField extends MultipicklistField +{ + /** {@inheritdoc} */ + protected $separator = ','; +}
app/Conditions/RecordFields/MailScannerFieldsField.php+19 −0 added@@ -0,0 +1,19 @@ +<?php +/** + * Mail scanner fields condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Mail scanner fields condition record field class. + */ +class MailScannerFieldsField extends MultiListFieldsField +{ +}
app/Conditions/RecordFields/MeetingUrlField.php+20 −0 added@@ -0,0 +1,20 @@ +<?php + +/** + * Meeting url condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Meeting url condition record field class. + */ +class MeetingUrlField extends UrlField +{ +}
app/Conditions/RecordFields/ModulesField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ModulesField extends BaseField
app/Conditions/RecordFields/MultiAttachmentField.php+19 −0 added@@ -0,0 +1,19 @@ +<?php +/** + * Multi attachment condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Multi attachment condition record field class. + */ +class MultiAttachmentField extends BaseField +{ +}
app/Conditions/RecordFields/MultiAttachment.php+19 −0 added@@ -0,0 +1,19 @@ +<?php +/** + * Multi attachment condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Multi attachment condition record field class. + */ +class MultiAttachment extends BaseField +{ +}
app/Conditions/RecordFields/MultiCurrencyField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/MultiDependFieldField.php+19 −0 added@@ -0,0 +1,19 @@ +<?php +/** + * Multi depend condition record field file. + * + * @package App + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Multi depend condition record field class. + */ +class MultiDependFieldField extends BaseField +{ +}
app/Conditions/RecordFields/MultiDomainField.php+24 −0 added@@ -0,0 +1,24 @@ +<?php +/** + * Multi domain condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Multi domain condition record field class. + */ +class MultiDomainField extends BaseField +{ + /** {@inheritdoc} */ + public function getValue() + { + return trim(parent::getValue(), ','); + } +}
app/Conditions/RecordFields/MultiEmailField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/MultiImageField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class MultiImageField extends BaseField
app/Conditions/RecordFields/MultiListFieldsField.php+21 −0 added@@ -0,0 +1,21 @@ +<?php +/** + * Multi list fields condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Multi list fields condition record field class. + */ +class MultiListFieldsField extends MultipicklistField +{ + /** {@inheritdoc} */ + protected $separator = ','; +}
app/Conditions/RecordFields/MultiownerField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/MultipicklistField.php+13 −7 modified@@ -1,19 +1,25 @@ <?php - -namespace App\Conditions\RecordFields; - /** - * Multi picklist condition record field class. + * Multi picklist condition record field file. * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ + +namespace App\Conditions\RecordFields; + +/** + * Multi picklist condition record field class. + */ class MultipicklistField extends BaseField { + /** @var string Separator. */ + protected $separator = ' |##| '; + /** {@inheritdoc} */ public function operatorE(): bool { @@ -45,6 +51,6 @@ public function operatorK(): bool /** {@inheritdoc} */ public function getValue(): array { - return explode(' |##| ', parent::getValue()); + return explode($this->separator, parent::getValue()); } }
app/Conditions/RecordFields/MultiReferenceField.php+21 −0 added@@ -0,0 +1,21 @@ +<?php +/** + * Multi reference condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Multi reference condition record field class. + */ +class MultiReferenceField extends MultipicklistField +{ + /** {@inheritdoc} */ + protected $separator = ','; +}
app/Conditions/RecordFields/MultiReferenceValueField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class MultiReferenceValueField extends BaseField
app/Conditions/RecordFields/OwnerField.php+22 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class OwnerField extends BaseField @@ -23,6 +23,26 @@ public function operatorWr() return \Vtiger_Watchdog_Model::getInstanceById($this->recordModel->getId(), $this->recordModel->getModuleName())->isWatchingRecord(); } + /** + * Users who belong to the same group as the currently logged in user. + * + * @return bool + */ + public function operatorOgu(): bool + { + $result = false; + $groups = \App\User::getCurrentUserModel()->getGroups(); + if ($groups) { + foreach (array_keys($groups) as $groupId) { + if (\in_array($this->getValue(), \App\PrivilegeUtil::getUsersByGroup((int) $groupId))) { + $result = true; + break; + } + } + } + return $result; + } + /** * Is not watching record operator. *
app/Conditions/RecordFields/PasswordField.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/PercentageField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class PercentageField extends IntegerField
app/Conditions/RecordFields/PhoneField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class PhoneField extends StringField
app/Conditions/RecordFields/PicklistField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/RangeTimeField.php+4 −2 modified@@ -7,10 +7,12 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class RangeTimeField extends BaseField { + use \App\Conditions\RecordTraits\Comparison; + use \App\Conditions\RecordTraits\ComparisonField; }
app/Conditions/RecordFields/RecordNumberField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class RecordNumberField extends StringField
app/Conditions/RecordFields/RecurrenceField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class RecurrenceField extends BooleanField
app/Conditions/RecordFields/ReferenceExtendField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ReferenceExtendField extends ReferenceField
app/Conditions/RecordFields/ReferenceField.php+3 −3 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -50,7 +50,7 @@ public function operatorC() } /** {@inheritdoc} */ - public function operatorK() + public function operatorK(): bool { return false === strpos(\App\Record::getLabel($this->getValue(), true), $this->value); }
app/Conditions/RecordFields/ReferenceLinkField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ReferenceLinkField extends ReferenceField
app/Conditions/RecordFields/ReferenceProcessField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ReferenceProcessField extends ReferenceField
app/Conditions/RecordFields/ReferenceSubProcessField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ReferenceSubProcessField extends ReferenceField
app/Conditions/RecordFields/ReferenceSubProcessSLField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) *@author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/ReminderField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ReminderField extends IntegerField
app/Conditions/RecordFields/SalutationField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class SalutationField extends StringField
app/Conditions/RecordFields/ServerAccessField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/SharedOwnerField.php+25 −2 modified@@ -7,10 +7,33 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class SharedOwnerField extends BaseField { + /** + * Users who belong to the same group as the currently logged in user. + * + * @return bool + */ + public function operatorOgu(): bool + { + $result = false; + $groups = \App\User::getCurrentUserModel()->getGroups(); + if ($groups) { + $usersByGroups = []; + foreach ($groups as $groupId) { + $usersByGroups[] = (new \App\Db\Query())->select(['userid'])->from(["condition_groups_{$groupId}_" . \App\Layout::getUniqueId() => \App\PrivilegeUtil::getQueryToUsersByGroup((int) $groupId)])->column(); + } + foreach ($usersByGroups as $usersByGroup) { + if (array_intersect(explode(',', $this->getValue()), $usersByGroup)) { + $result = true; + break; + } + } + } + return $result; + } }
app/Conditions/RecordFields/SkypeField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class SkypeField extends StringField
app/Conditions/RecordFields/SmtpField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/StringField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class StringField extends BaseField
app/Conditions/RecordFields/TaxesField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class TaxesField extends MultipicklistField
app/Conditions/RecordFields/TextField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class TextField extends StringField
app/Conditions/RecordFields/ThemeField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class ThemeField extends BaseField
app/Conditions/RecordFields/TimeField.php+4 −2 modified@@ -7,10 +7,12 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class TimeField extends BaseField { + use \App\Conditions\RecordTraits\Comparison; + use \App\Conditions\RecordTraits\ComparisonField; }
app/Conditions/RecordFields/TokenField.php+19 −0 added@@ -0,0 +1,19 @@ +<?php +/** + * Token condition record field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordFields; + +/** + * Token condition record field class. + */ +class TokenField extends StringField +{ +}
app/Conditions/RecordFields/TotalTimeField.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/RecordFields/TreeField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class TreeField extends StringField
app/Conditions/RecordFields/TwitterField.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Conditions/RecordFields/UrlField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class UrlField extends StringField
app/Conditions/RecordFields/UserCreatorField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Conditions/RecordFields/UserReferenceField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class UserReferenceField extends OwnerField
app/Conditions/RecordFields/UserRoleField.php+2 −2 modified@@ -7,8 +7,8 @@ * * @package UIType * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ class UserRoleField extends StringField
app/Conditions/RecordTraits/ComparisonField.php+58 −0 added@@ -0,0 +1,58 @@ +<?php +/** + * Record comparison field file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordTraits; + +/** + * Record comparison field class. + */ +trait ComparisonField +{ + /** + * Less than field operator. + * + * @return bool + */ + public function operatorLf(): bool + { + return $this->getValue() < $this->getValueFromSource(); + } + + /** + * Greater than field operator. + * + * @return bool + */ + public function operatorGf(): bool + { + return $this->getValue() > $this->getValueFromSource(); + } + + /** + * Less than field or equal operator. + * + * @return bool + */ + public function operatorMf(): bool + { + return $this->getValue() <= $this->getValueFromSource(); + } + + /** + * Greater than field or equal operator. + * + * @return bool + */ + public function operatorHf(): bool + { + return $this->getValue() >= $this->getValueFromSource(); + } +}
app/Conditions/RecordTraits/Comparison.php+58 −0 added@@ -0,0 +1,58 @@ +<?php +/** + * Record comparison file. + * + * @package UIType + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Conditions\RecordTraits; + +/** + * Record comparison class. + */ +trait Comparison +{ + /** + * Less than operator. + * + * @return bool + */ + public function operatorL(): bool + { + return $this->getValue() < $this->value; + } + + /** + * Greater than operator. + * + * @return bool + */ + public function operatorG(): bool + { + return $this->getValue() > $this->value; + } + + /** + * Less than or equal to operator. + * + * @return bool + */ + public function operatorM(): bool + { + return $this->getValue() <= $this->value; + } + + /** + * Greater than or equal to operator. + * + * @return bool + */ + public function operatorH(): bool + { + return $this->getValue() >= $this->value; + } +}
app/ConfigFile.php+12 −6 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -51,8 +51,8 @@ class ConfigFile extends Base @package Config -@copyright YetiForce Sp. z o.o -@license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) +@copyright YetiForce S.A. +@license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) '; /** @@ -234,10 +234,16 @@ public function create() $class->addComment("Configuration file: $className."); foreach ($this->template as $parameterName => $parameter) { if (isset($parameter['type']) && 'function' === $parameter['type']) { - $class->addMethod($parameterName)->setStatic()->setBody($parameter['default'])->addComment($parameter['description']); + $property = $class->addMethod($parameterName)->setStatic()->setBody($parameter['default'])->addComment($parameter['description']); } else { $value = $this->has($parameterName) ? $this->get($parameterName) : Config::get($className, $parameterName, $parameter['default']); - $class->addProperty($parameterName, $value)->setStatic()->addComment($parameter['description']); + $property = $class->addProperty($parameterName, $value)->setStatic()->addComment($parameter['description']); + } + if (isset($parameter['docTags'])) { + foreach ($parameter['docTags'] as $tagName => $val) { + $property->addComment(''); + $property->addComment("@{$tagName} {$val}"); + } } } if (false === file_put_contents($this->path, $file, LOCK_EX)) {
app/Config.php+29 −3 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -327,13 +327,39 @@ public static function set(): bool { if (4 === \func_num_args()) { [$component, $type, $key, $value] = \func_get_args(); + $component = ucfirst($component) . 's\\'; } else { [$type, $key, $value] = \func_get_args(); + $type = ucfirst($type); } - $class = '\Config\\' . (isset($component) ? ucfirst($component) . 's\\' : '') . ucfirst($type); + $class = '\Config\\' . ($component ?? '') . $type; if ($result = (class_exists($class) && isset($class::${$key}))) { $class::${$key} = $value; } return $result; } + + /** + * Get the maximum size of an uploaded file to the server taking into account CRM configuration and server settings. + * + * @param bool $checkMain + * @param bool $returnInMb + * + * @return int + */ + public static function getMaxUploadSize(bool $checkMain = true, bool $returnInMb = false): int + { + $size = \vtlib\Functions::parseBytes(ini_get('upload_max_filesize')); + $maxPostSize = \vtlib\Functions::parseBytes(ini_get('post_max_size')); + if ($maxPostSize < $size) { + $size = $maxPostSize; + } + if ($checkMain && \Config\Main::$upload_maxsize < $size) { + $size = (int) \Config\Main::$upload_maxsize; + } + if ($returnInMb) { + $size = floor($size / 1048576); + } + return $size; + } }
app/Controller/Action.php+3 −5 modified@@ -4,9 +4,10 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace App\Controller; @@ -16,9 +17,6 @@ */ abstract class Action extends Base { - /** {@inheritdoc} */ - public $csrfActive = false; - /** * Process action. *
app/Controller/Base.php+11 −28 modified@@ -4,9 +4,10 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace App\Controller; @@ -18,25 +19,12 @@ abstract class Base { /** @var \App\Headers Headers instance. */ public $headers; - /** - * CSRF is active?. - * - * @var bool - */ - public $csrfActive = true; - /** - * Activated language locale. - * - * @var bool - */ + /** @var bool Activated language locale. */ protected static $activatedLocale = false; - /** - * Activated csrf. - * - * @var bool - */ - protected static $activatedCsrf = false; + + /** @var bool CSRF already initiated. */ + private static $csrfInitiated = false; /** * Constructor. @@ -48,15 +36,10 @@ public function __construct() \App\Language::initLocale(); self::$activatedLocale = true; } - if (!self::$activatedCsrf) { - if ($this->csrfActive && \App\Config::security('csrfActive')) { - require_once 'config/csrf_config.php'; - \CsrfMagic\Csrf::init(); - $this->csrfActive = true; - } else { - $this->csrfActive = false; - } - self::$activatedCsrf = true; + if (\App\Config::security('csrfActive') && !self::$csrfInitiated) { + require_once 'config/csrf_config.php'; + \CsrfMagic\Csrf::init(); + self::$csrfInitiated = true; } }
app/Controller/ClearProcess.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Controller/Components/Action/InterestsConflict.php+18 −18 modified@@ -4,8 +4,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -55,7 +55,7 @@ public function checkPermission(\App\Request $request) /** * Get unlock data. * - * @param App\Request $request + * @param \App\Request $request * * @return void */ @@ -68,7 +68,7 @@ public function getUnlock(\App\Request $request): void /** * Get confirmations data. * - * @param App\Request $request + * @param \App\Request $request * * @return void */ @@ -81,7 +81,7 @@ public function getConfirm(\App\Request $request): void /** * Save unlock data. * - * @param App\Request $request + * @param \App\Request $request * * @return void */ @@ -95,7 +95,7 @@ public function updateUnlockStatus(\App\Request $request): void /** * Save confirmations data. * - * @param App\Request $request + * @param \App\Request $request * * @return void */ @@ -109,7 +109,7 @@ public function updateConfirmStatus(\App\Request $request): void /** * Get response. * - * @param App\Request $request + * @param \App\Request $request * * @return array */ @@ -126,7 +126,7 @@ public function getUnlockResponse(\App\Request $request): array 'user_id' => \App\Fields\Owner::getUserLabel($row['user_id']), 'related' => $row['related_id'], 'source_id' => $row['source_id'], - 'comment' => nl2br(\App\Layout::truncateText($row['comment'], 40)), + 'comment' => \App\Layout::truncateText($row['comment'], 40, true, true), 'modify_user' => $row['modify_user_id'] ? \App\Fields\Owner::getUserLabel($row['modify_user_id']) : null, 'modify_date_time' => $row['modify_date_time'] ? \App\Fields\DateTime::formatToDisplay($row['modify_date_time']) : null, ]; @@ -135,10 +135,10 @@ public function getUnlockResponse(\App\Request $request): array \App\Record::getLabel($ids); \vtlib\Functions::getCRMRecordMetadata($ids); foreach ($rows as &$row) { - $row['related'] = \App\Layout::getRecordLabel($row['related']); + $row['related'] = \App\Record::getHtmlLink($row['related'], null, \App\Config::main('href_max_length')); $info = ''; if ($row['source_id']) { - $info .= \App\Language::translate('LBL_SOURCE_RECORD') . ': ' . \App\Layout::getRecordLabel($row['source_id']) . '<br>'; + $info .= \App\Language::translate('LBL_SOURCE_RECORD') . ': ' . \App\Record::getHtmlLink($row['source_id'], null, \App\Config::main('href_max_length')) . '<br>'; } if ($row['modify_user']) { $info .= \App\Language::translate('Last Modified By') . ': ' . $row['modify_user'] . '<br>'; @@ -160,9 +160,9 @@ public function getUnlockResponse(\App\Request $request): array /** * Get query. * - * @param App\Request $request + * @param \App\Request $request * - * @return App\Db\Query + * @return \App\Db\Query */ public function getUnlockQuery(\App\Request $request): \App\Db\Query { @@ -196,7 +196,7 @@ public function getUnlockQuery(\App\Request $request): \App\Db\Query /** * Get response. * - * @param App\Request $request + * @param \App\Request $request * * @return array */ @@ -231,10 +231,10 @@ public function getConfirmResponse(\App\Request $request): array \App\Record::getLabel($ids); \vtlib\Functions::getCRMRecordMetadata($ids); foreach ($rows as &$row) { - $row['related'] = \App\Layout::getRecordLabel($row['related_id']); + $row['related'] = \App\Record::getHtmlLink($row['related_id'], null, \App\Config::main('href_max_length')); $info = ''; if ($row['source_id']) { - $info .= \App\Language::translate('LBL_SOURCE_RECORD') . ': ' . \App\Layout::getRecordLabel($row['source_id']) . '<br>'; + $info .= \App\Language::translate('LBL_SOURCE_RECORD') . ': ' . \App\Record::getHtmlLink($row['source_id'], null, \App\Config::main('href_max_length')) . '<br>'; } if ($row['modify_user']) { $info .= \App\Language::translate('Last Modified By') . ': ' . $row['modify_user'] . '<br>'; @@ -263,10 +263,10 @@ public function getConfirmResponse(\App\Request $request): array /** * Get query. * - * @param App\Request $request - * @param string $type + * @param \App\Request $request + * @param string $type * - * @return App\Db\Query + * @return \App\Db\Query */ public function getConfirmQuery(\App\Request $request, string $type): \App\Db\Query {
app/Controller/Components/View/ColorPickerModal.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Tomasz Poradzewski <t.poradzewski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com>
app/Controller/Components/View/InterestsConflict.php+2 −3 modified@@ -4,8 +4,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ @@ -76,7 +76,6 @@ public function process(\App\Request $request) public function getFooterScripts(\App\Request $request) { return array_merge(parent::getFooterScripts($request), $this->checkAndConvertJsScripts([ - '~libraries/datatables.net/js/jquery.dataTables.js', '~libraries/datatables.net/js/jquery.dataTables.js', '~libraries/datatables.net-bs4/js/dataTables.bootstrap4.js', '~libraries/datatables.net-responsive/js/dataTables.responsive.js',
app/Controller/Components/View/MailMessageAnalysisModal.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Controller/Components/View/MediaModal.php+56 −0 added@@ -0,0 +1,56 @@ +<?php +/** + * Icon modal view class file. + * + * @package Controller + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> + */ + +namespace App\Controller\Components\View; + +/** + * Icon modal view class. + */ +class MediaModal extends \App\Controller\Modal +{ + /** {@inheritdoc} */ + protected $pageTitle = 'LBL_MEDIA'; + /** {@inheritdoc} */ + public $modalSize = 'c-modal-xxl'; + /** {@inheritdoc} */ + public $modalIcon = 'fas fa-icons'; + /** {@inheritdoc} */ + public $successBtn = ''; + + /** {@inheritdoc} */ + public function checkPermission(\App\Request $request) + { + return true; + } + + /** {@inheritdoc} */ + public function process(\App\Request $request) + { + $viewer = $this->getViewer($request); + $viewer->assign('ICONS', \App\Layout\Icon::getIcons()); + $viewer->assign('IMAGES', \App\Layout\Media::getImages()); + $viewer->assign('PAGE_LIMT', 100); + if (\App\Security\AdminAccess::isPermitted('Media')) { + $moduleModel = \Settings_Vtiger_Module_Model::getInstance('Settings:Media'); + $fieldModel = $moduleModel->getFieldInstanceByName('image'); + $viewer->assign('FIELD_MODEL', $fieldModel); + } + $viewer->view('MediaModal.tpl', $request->getModule()); + } + + /** {@inheritdoc} */ + public function getModalScripts(\App\Request $request) + { + return array_merge(parent::getModalScripts($request), $this->checkAndConvertJsScripts([ + 'components.MediaModal', + ])); + } +}
app/Controller/Components/View/YetiForceDetailModal.php+46 −0 added@@ -0,0 +1,46 @@ +<?php +/** + * YetiForce detail modal view file. + * + * @package Controller + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Arkadiusz Sołek <a.solek@yetiforce.com> + */ + +namespace App\Controller\Components\View; + +/** + * YetiForce detail modal view class. + */ +class YetiForceDetailModal extends \App\Controller\Modal +{ + /** {@inheritdoc} */ + public $successBtn = ''; + /** {@inheritdoc} */ + public $dangerBtn = 'LBL_CLOSE'; + /** {@inheritdoc} */ + public $modalSize = 'modal-xl'; + + /** {@inheritdoc} */ + public function checkPermission(\App\Request $request) + { + return true; + } + + /** {@inheritdoc} */ + public function getPageTitle(\App\Request $request) + { + $version = \App\User::getCurrentUserModel()->isAdmin() ? 'v' . \App\Version::get() : ''; + $titleModal = \App\Language::translate('LBL_YETIFORCE_CRM_INFO'); + return "YetiForceCRM {$version} - {$titleModal}"; + } + + /** {@inheritdoc} */ + public function process(\App\Request $request) + { + $viewer = $this->getViewer($request); + $viewer->view('YetiForceDetailModal.tpl', $request->getModule()); + } +}
app/Controller/ExposeMethod.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Controller/Headers.php+10 −2 modified@@ -4,9 +4,10 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ namespace App\Controller; @@ -45,6 +46,7 @@ class Headers public $csp = [ 'default-src' => '\'self\' blob:', 'img-src' => '\'self\' data:', + 'font-src' => '\'self\' data:', 'script-src' => '\'self\' \'unsafe-inline\' blob:', 'form-action' => '\'self\'', 'frame-ancestors' => '\'self\'', @@ -173,6 +175,12 @@ public function loadCsp() if (\Config\Security::$allowedFrameDomains) { $this->csp['frame-ancestors'] .= ' ' . \implode(' ', \Config\Security::$allowedFrameDomains); } + if (\Config\Security::$allowedConnectDomains) { + $this->csp['connect-src'] .= ' ' . \implode(' ', \Config\Security::$allowedConnectDomains); + } + if (\Config\Security::$allowedDomainsLoadInFrame) { + $this->csp['frame-src'] .= ' ' . \implode(' ', \Config\Security::$allowedDomainsLoadInFrame); + } } /**
app/Controller/Modal.php+2 −2 modified@@ -5,8 +5,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Controller/ModalSettings.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Sławomir Kłos <s.klos@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Controller/Traits/RecordSettings.php+98 −0 added@@ -0,0 +1,98 @@ +<?php +/** + * Abstract modal controller for administration panel file. + * + * @package Controller + * + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> + */ + +namespace App\Controller\Traits; + +/** + * Record settings basic controller trait. + */ +trait RecordSettings +{ + /** + * Record ID. + * + * @return int + */ + public function getId() + { + return $this->get('id'); + } + + /** + * Record name. + * + * @return string + */ + public function getName() + { + return $this->get('url'); + } + + /** + * Get record links. + * + * @return Vtiger_Link_Model[] + */ + public function getRecordLinks(): array + { + $links = []; + foreach ([ + [ + 'linktype' => 'LISTVIEWRECORD', + 'linklabel' => 'BTN_RECORD_EDIT', + 'linkdata' => ['url' => $this->getEditViewUrl()], + 'linkicon' => 'yfi yfi-full-editing-view', + 'linkclass' => 'btn btn-sm btn-primary js-edit-record-modal', + ], + [ + 'linktype' => 'LISTVIEWRECORD', + 'linklabel' => 'LBL_DELETE_RECORD', + 'linkurl' => "javascript:Settings_Vtiger_List_Js.deleteById('{$this->getId()}')", + 'linkicon' => 'fas fa-trash-alt', + 'linkclass' => 'btn btn-sm btn-danger text-white', + ], + ] as $recordLink) { + $links[] = \Vtiger_Link_Model::getInstanceFromValues($recordLink); + } + return $links; + } + + /** + * Function to delete the current record model. + * + * @return int + */ + public function delete(): int + { + return \App\Db::getInstance()->createCommand() + ->delete($this->getModule()->baseTable, ['id' => $this->getId()]) + ->execute(); + } + + /** + * Sets data from request. + * + * @param \App\Request $request + * + * @return void + */ + public function setDataFromRequest(\App\Request $request): void + { + foreach ($this->getModule()->getFormFields() as $fieldName => $fieldInfo) { + if ($request->has($fieldName)) { + $value = $request->getByType($fieldName, $fieldInfo['purifyType']); + $fieldModel = $this->getFieldInstanceByName($fieldName)->getUITypeModel(); + $fieldModel->validate($value, true); + $this->set($fieldName, $fieldModel->getDBValue($value)); + } + } + } +}
app/Controller/Traits/SettingsPermission.php+3 −3 modified@@ -1,12 +1,12 @@ <?php /** - * Admin privilege basic trait. + * Admin privilege basic trait file. * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/Controller/View/Base.php+4 −7 modified@@ -4,8 +4,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -224,7 +224,6 @@ public function getHeaderCss(\App\Request $request) '~libraries/clockpicker/dist/bootstrap4-clockpicker.css', '~libraries/animate.css/animate.css', '~libraries/tributejs/dist/tribute.css', - '~libraries/emojipanel/dist/emojipanel.css', '~libraries/emoji-mart-vue-fast/css/emoji-mart.css', '~libraries/overlayscrollbars/css/OverlayScrollbars.css', '~src/css/quasar.css', @@ -258,7 +257,6 @@ public function getHeaderScripts(\App\Request $request) '~libraries/quasar/dist/quasar.ie.polyfills.umd.min.js', '~libraries/whatwg-fetch/dist/fetch.umd.js', '~libraries/url-polyfill/url-polyfill.js', - '~libraries/gridstack/dist/gridstack-poly.min.js', ]; $jsFileNames = array_merge($polyfills, $jsFileNames); } @@ -291,7 +289,6 @@ public function getFooterScripts(\App\Request $request) '~libraries/popper.js/dist/umd/popper.js', '~libraries/bootstrap/dist/js/bootstrap.js', '~libraries/bootstrap-tabdrop/js/bootstrap-tabdrop.js', - '~libraries/bootbox/dist/bootbox.min.js', '~libraries/microplugin/src/microplugin.js', '~libraries/sifter/sifter.js', '~libraries/jQuery-Validation-Engine/js/jquery.validationEngine.js', @@ -303,7 +300,6 @@ public function getFooterScripts(\App\Request $request) '~vendor/ckeditor/ckeditor/ckeditor.js', '~vendor/ckeditor/ckeditor/adapters/jquery.js', '~libraries/tributejs/dist/tribute.js', - '~libraries/emojipanel/dist/emojipanel.js', '~libraries/vue/dist/vue.js', '~layouts/resources/libraries/quasar.config.js', '~libraries/quasar/dist/quasar.umd.min.js', @@ -484,9 +480,10 @@ public function loadJsConfig(\App\Request $request) 'rowHeight' => $userModel->getDetail('rowheight'), 'userId' => $userModel->getId(), 'purifierAllowedDomains' => \App\Config::security('purifierAllowedDomains', []), + 'globalSearchDefaultOperator' => \App\RecordSearch::OPERATORS[$userModel->getDetail('default_search_operator')], + 'maxUploadLimit' => \App\Config::getMaxUploadSize(), // Modifying this file or functions that affect the footer appearance will violate the license terms!!! 'disableBranding' => \App\YetiForce\Shop::check('YetiForceDisableBranding'), - 'globalSearchDefaultOperator' => \App\RecordSearch::OPERATORS[$userModel->getDetail('default_search_operator')], ]; } foreach ($jsEnv as $key => $value) {
app/Controller/View/Page.php+16 −4 modified@@ -4,8 +4,8 @@ * * @package Controller * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -97,7 +97,7 @@ public function getFooterScripts(\App\Request $request) $jsFileNames[] = "modules.$moduleName.resources.Edit"; $jsFileNames[] = "modules.$moduleName.resources.AdvanceFilter"; } - if (\App\Privilege::isPermitted('OSSMail')) { + if (\App\Mail::checkMailClient()) { $jsFileNames[] = '~layouts/basic/modules/OSSMail/resources/checkmails.js'; } if (!\App\RequestUtil::getBrowserInfo()->ie) { @@ -223,11 +223,23 @@ protected function getUserQuickMenuLinks(\App\Request $request): array $headerLinks[] = [ 'linktype' => 'HEADERLINK', 'linklabel' => 'LBL_CHANGE_PASSWORD', - 'linkdata' => ['url' => 'index.php?module=Users&view=PasswordModal&mode=change&record=' . $userModel->get('id')], + 'linkdata' => ['url' => 'index.php?module=Users&view=PasswordModal&mode=change&record=' . $userModel->getId()], 'linkclass' => 'showModal d-block', 'icon' => 'yfi yfi-change-passowrd', ]; } + if ( + ('PLL_PASSWORD_2FA' === $userModel->get('login_method') || 'PLL_LDAP_2FA' === $userModel->get('login_method')) + && $userModel->getId() === \App\User::getCurrentUserRealId() && 'TOTP_OFF' !== \App\Config::security('USER_AUTHY_MODE') + ) { + $headerLinks[] = [ + 'linktype' => 'HEADERLINK', + 'linklabel' => 'LBL_2FA_TOTP_QR_CODE', + 'linkdata' => ['url' => 'index.php?module=Users&view=TwoFactorAuthenticationModal&record=' . $userModel->getId()], + 'linkclass' => 'showModal d-block', + 'icon' => 'fas fa-key', + ]; + } if (\Users_Module_Model::getSwitchUsers()) { $headerLinks[] = [ 'linktype' => 'HEADERLINK',
app/CronHandler.php+17 −7 modified@@ -4,9 +4,10 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Tomasz Kur <t.kur@yetiforce.com> + * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */ namespace App; @@ -16,13 +17,12 @@ */ abstract class CronHandler { - /** - * Cron task instance. - * - * @var \vtlib\Cron - */ + /** @var \vtlib\Cron Cron task instance. */ protected $cronTask; + /** @var string Cron task logs. */ + protected $logs = ''; + /** * Main function to execute task. * @@ -59,4 +59,14 @@ public function updateLastActionTime(): void { $this->cronTask->updateLastActionTime(); } + + /** + * Get cron task logs. + * + * @return string + */ + public function getTaskLog(): string + { + return $this->logs; + } }
app/Cron.php+2 −2 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Sławomir Kłos <s.klos@yetiforce.com> * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> */
app/CustomView.php+11 −7 modified@@ -4,8 +4,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -251,7 +251,7 @@ private function getColumnsByCvidFromDb($cvId) \App\Log::trace(__METHOD__ . ' - ' . $cvId); $columnList = []; if (is_numeric($cvId)) { - $dataReader = (new Db\Query())->select(['field_name', 'module_name', 'source_field_name']) + $dataReader = (new Db\Query())->select(['field_name', 'module_name', 'source_field_name', 'label']) ->from('vtiger_cvcolumnlist') ->innerJoin('vtiger_tab', 'vtiger_tab.name=vtiger_cvcolumnlist.module_name') ->innerJoin('vtiger_field', 'vtiger_tab.tabid = vtiger_field.tabid AND vtiger_field.fieldname = vtiger_cvcolumnlist.field_name') @@ -725,7 +725,10 @@ public static function getCustomViewById(int $cvId): array if (Cache::has('CustomViewById', $cvId)) { return Cache::get('CustomViewById', $cvId); } - $data = (new Db\Query())->from('vtiger_customview')->where(['cvid' => $cvId])->one(); + $data = (new Db\Query())->from('vtiger_customview')->where(['cvid' => $cvId])->one() ?: []; + if (!empty($data['advanced_conditions'])) { + $data['advanced_conditions'] = \App\Json::decode($data['advanced_conditions']); + } Cache::save('CustomViewById', $cvId, $data); return $data; } @@ -744,9 +747,9 @@ public static function getCVDetails(int $cvId, string $moduleName = null): array return Cache::get('CustomViewInfo', $cvId); } if (!$moduleName) { - $moduleName = self::getCustomViewById($cvId)['entitytype']; + $moduleName = self::getCustomViewById($cvId)['entitytype'] ?? ''; } - return self::getFiltersByModule($moduleName)[$cvId] ?? []; + return $moduleName ? (self::getFiltersByModule($moduleName)[$cvId] ?? []) : []; } /** @@ -761,13 +764,14 @@ public static function clearCacheById(int $cvId, string $moduleName = null): voi { Cache::delete('CustomViewById', $cvId); Cache::delete('CustomViewInfo', $cvId); - Cache::delete('CustomViewInfo', $moduleName); Cache::delete('getAllFilterColors', false); Cache::delete('getAllFilterColors', true); if (null === $moduleName) { foreach (\App\Module::getAllModuleNames() as $moduleName) { Cache::delete('CustomViewInfo', $moduleName); } + } else { + Cache::delete('CustomViewInfo', $moduleName); } } }
app/Db/Command.php+2 −2 modified@@ -1,7 +1,7 @@ <?php /** - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */
app/Db.php+3 −3 modified@@ -7,8 +7,8 @@ * * @package App * - * @copyright YetiForce Sp. z o.o - * @license YetiForce Public License 4.0 (licenses/LicenseEN.txt or yetiforce.com) + * @copyright YetiForce S.A. + * @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) * @author Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com> * @author Radosław Skrzypczak <r.skrzypczak@yetiforce.com> */ @@ -248,7 +248,7 @@ public function quoteSql($sql) * * @return string the row ID of the last row inserted, or the last value retrieved from the sequence object * - * @see http://www.php.net/manual/en/function.PDO-lastInsertId.php + * @see https://www.php.net/manual/en/function.PDO-lastInsertId.php */ public function getLastInsertID($sequenceName = '') {
Dockerfile+1 −1 modified@@ -1,4 +1,4 @@ -FROM debian:buster +FROM debian:bullseye MAINTAINER m.krzaczkowski@yetiforce.com
.github/ISSUE_TEMPLATE/4-security.md+0 −5 modified@@ -16,11 +16,6 @@ Thank you! PGP key: -### m.krzaczkowski@yetiforce.com -- https://keys.openpgp.org/search?q=m.krzaczkowski%40yetiforce.com -- https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x67ab74c22359e45a56f019a1421e62f3637ff007 -- https://keyserver2.pgp.com/vkd/SubmitSearch.event?SearchCriteria=m.krzaczkowski%40yetiforce.com - ### security@yetiforce.com - https://keys.openpgp.org/search?q=security%40yetiforce.com - https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x0fecf61043925c9b9e16ef29bcaeb2432daf21e4
.github/SECURITY.md+1 −7 renamed@@ -5,13 +5,7 @@ If you find (or simply suspect) a security issue, please report it to us and send an email to security@yetiforce.com with a description of the issue, the steps you took to create the issue, affected versions, and, if known, mitigations for the issue. We take security very seriously and our team will try to resolve the issue as quickly as possible. -PGP key: -### m.krzaczkowski@yetiforce.com -- https://keys.openpgp.org/search?q=m.krzaczkowski%40yetiforce.com -- https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x67ab74c22359e45a56f019a1421e62f3637ff007 -- https://keyserver2.pgp.com/vkd/SubmitSearch.event?SearchCriteria=m.krzaczkowski%40yetiforce.com - -### security@yetiforce.com +PGP key: - https://keys.openpgp.org/search?q=security%40yetiforce.com - https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x0fecf61043925c9b9e16ef29bcaeb2432daf21e4 - https://keyserver2.pgp.com/vkd/SubmitSearch.event?&&SearchCriteria=security%40yetiforce.com
.github/workflows/actions.yml+20 −16 modified@@ -13,15 +13,18 @@ jobs: name: Composer runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 + - name: 🔎 Check IP + run: curl https://api.ipify.org + - name: Validate composer.json and composer.lock run: composer validate - name: Cache Composer dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: /tmp/composer-cache key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }} @@ -34,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 @@ -57,13 +60,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: - java-version: 1.8 + distribution: 'temurin' + java-version: 18 - name: Upload to CoPilot run: bash <(curl -s https://copilot.blackducksoftware.com/ci/githubactions/scripts/upload) @@ -74,28 +78,28 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Validate OpenAPI definition - WebservicePremium.yaml - uses: char0n/swagger-editor-validate@v1.2.1 + uses: char0n/swagger-editor-validate@v1.3.1 with: - definition-file: public_html/api/WebservicePremium.yaml + definition-file: api/doc/WebservicePremium.yaml - name: Validate OpenAPI definition - ManageConsents.yaml - uses: char0n/swagger-editor-validate@v1.2.1 + uses: char0n/swagger-editor-validate@v1.3.1 with: - definition-file: public_html/api/ManageConsents.yaml + definition-file: api/doc/ManageConsents.yaml - name: Validate OpenAPI definition - WebserviceStandard.yaml - uses: char0n/swagger-editor-validate@v1.2.1 + uses: char0n/swagger-editor-validate@v1.3.1 with: - definition-file: public_html/api/WebserviceStandard.yaml + definition-file: api/doc/WebserviceStandard.yaml gitGuardian: name: GitGuardian scan runs-on: ubuntu-latest steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 @@ -119,12 +123,12 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Lint Code Base - uses: docker://github/super-linter:v3.17.2 + uses: docker://github/super-linter:v4.9.6 env: DEFAULT_BRANCH: developer FILTER_REGEX_EXCLUDE: .*(*.min.js|*.min.css).*s
.github/workflows/code-analysis.yml+7 −7 modified@@ -10,23 +10,23 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -40,14 +40,14 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 Code: runs-on: ubuntu-latest name: Static Code Analysis steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis @@ -81,13 +81,13 @@ jobs: # Scan auto-detects the languages in your project. To override uncomment the below variable and set the type #type: php,javascript,json,nodejs,plsql,yaml,depscan - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: shiftleft-scan-reports path: reports - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: javascript.zip path: /home/runner/work/_temp/codeql_databases/javascript.zip
.github/workflows/doc-checker.yml+43 −0 added@@ -0,0 +1,43 @@ +name: phpDoc Checker + +on: + push: + branches: + - developer + +jobs: + phpDoc: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: [7.4, 8.0] + name: Doc Checker PHP${{ matrix.php }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + ini-values: memory_limit=512M, xdebug.mode=off + + - name: wget + shell: bash + run: | + wget https://phpdoc.org/phpDocumentor.phar -P /tmp/ + chmod +x /tmp/phpDocumentor.phar + + - name: phpDocumentor + shell: bash + run: php /tmp/phpDocumentor.phar run -d . -t phpDoc/ --sourcecode + + - name: Checker + shell: bash + run: | + if [ "$(grep -c 'No errors have been found in this project.' phpDoc/reports/errors.html)" = 0 ]; then + cat phpDoc/reports/errors.html + exit 3 + fi
.github/workflows/scorecards-analysis.yml+55 −0 added@@ -0,0 +1,55 @@ +name: Scorecards supply-chain security +on: + # Only the default branch is supported. + branch_protection_rule: + schedule: + - cron: '36 5 * * 2' + push: + branches: [developer] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecards analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + actions: read + contents: read + + steps: + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + persist-credentials: false + + - name: 'Run analysis' + uses: ossf/scorecard-action@v1.1.2 + with: + results_file: results.sarif + results_format: sarif + # Read-only PAT token. To create it, + # follow the steps in https://github.com/ossf/scorecard-action#pat-token-creation. + repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} + # Publish the results to enable scorecard badges. For more details, see + # https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories, `publish_results` will automatically be set to `false`, + # regardless of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). + - name: 'Upload artifact' + uses: actions/upload-artifact@v3 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: 'Upload to code-scanning' + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: results.sarif
.github/workflows/semgrep.yml+19 −0 added@@ -0,0 +1,19 @@ +on: + pull_request: {} + push: + branches: + - developer + paths: + - .github/workflows/semgrep.yml + schedule: + - cron: '0 0 * * 0' +name: Semgrep +jobs: + semgrep: + name: Scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: returntocorp/semgrep-action@v1 + with: + publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
.github/workflows/tests.yml+95 −35 modified@@ -6,53 +6,82 @@ on: - developer jobs: - tests73: + tests74: runs-on: ubuntu-latest - name: PHP 7.3 - MariaDB 10 + name: PHP 7.4 - MariaDB 10.5 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Tests - uses: YetiForceCompany/YetiForceCRM-Tests/7.3@main + uses: YetiForceCompany/YetiForceCRM-Tests/7.4@main env: YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} - tests74: + tests80: runs-on: ubuntu-latest - name: PHP 7.4 - MariaDB 10 + name: PHP 8.0 - MariaDB 10.5 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: - fetch-depth: 0 + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Tests - uses: YetiForceCompany/YetiForceCRM-Tests/7.4@main + uses: YetiForceCompany/YetiForceCRM-Tests/8.0@main env: YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} - tests80: + tests81: runs-on: ubuntu-latest - name: PHP 8.0 - MariaDB 10 + name: PHP 8.1 - MariaDB 10.5 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Tests - uses: YetiForceCompany/YetiForceCRM-Tests/8.0@main + uses: YetiForceCompany/YetiForceCRM-Tests/8.1@main + env: + YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} + YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} + + tests80jit: + runs-on: ubuntu-latest + name: PHP 8.0 JIT - MariaDB 10.5 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Tests + uses: YetiForceCompany/YetiForceCRM-Tests/8.0-JIT@main + env: + YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} + YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} + + tests81jit: + runs-on: ubuntu-latest + name: PHP 8.1 JIT - MariaDB 10.5 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Tests + uses: YetiForceCompany/YetiForceCRM-Tests/8.1-JIT@main env: YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} tests74MariaDB106: + needs: tests80 runs-on: ubuntu-latest name: PHP 7.4 - MariaDB 10.6 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis @@ -62,11 +91,57 @@ jobs: YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} + tests74MariaDB107: + needs: tests80 + runs-on: ubuntu-latest + name: PHP 7.4 - MariaDB 10.7 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Tests + uses: YetiForceCompany/YetiForceCRM-Tests/mariadb-10.7@main + env: + YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} + YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} + + tests74MariaDB108: + needs: tests80 + runs-on: ubuntu-latest + name: PHP 7.4 - MariaDB 10.8 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Tests + uses: YetiForceCompany/YetiForceCRM-Tests/mariadb-10.8@main + env: + YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} + YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} + + tests74MariaDB109: + needs: tests80 + runs-on: ubuntu-latest + name: PHP 7.4 - MariaDB 10.9 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Tests + uses: YetiForceCompany/YetiForceCRM-Tests/mariadb-10.9@main + env: + YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} + YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} + tests74MySQL57: + needs: tests80 runs-on: ubuntu-latest - name: PHP 7.4 - Percona MySQL 5.7 + name: PHP 7.4 - MySQL 5.7 Percona steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis @@ -77,10 +152,11 @@ jobs: YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} coverage: + needs: tests80 runs-on: ubuntu-latest name: Code Coverage steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis @@ -111,30 +187,14 @@ jobs: coverageLocations: ${{github.workspace}}/tests/coverages/coverage3.xml:clover - name: Upload artifact Coverages - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: Coverages path: ${{github.workspace}}/tests/coverages - name: Upload artifact Logs if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: Logs path: ${{github.workspace}}/cache/logs/ - - coverage8: - runs-on: ubuntu-latest - name: Code Coverage PHP8 - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - - name: Tests - uses: YetiForceCompany/YetiForceCRM-Tests/coverage@main - env: - YETI_TEST_MODULE_KEY: ${{ secrets.YETI_TEST_MODULE_KEY }} - YETI_MAIL_PASS: ${{ secrets.YETI_MAIL_PASS }} - CODACY_PROJECT_TOKEN: ${{ secrets.YETI_CODACY_PROJECT_TOKEN }} - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
.htaccess+1 −1 modified@@ -42,7 +42,7 @@ RedirectMatch 403 (?i).*\.log$ <IfModule mod_php5.c> php_flag output_buffering On php_flag always_populate_raw_post_data Off - php_flag mbstring.func_overload Off + php_flag mbstring.func_overload 0 </IfModule> </Files> ########################
LICENSE+4 −4 modified@@ -1,13 +1,13 @@ -YetiForce Public License 4.0 -Producer: YetiForce Sp. z o.o., PL1180002425 +YetiForce Public License 5.0 +Producer: YetiForce S.A., PL1180002425 Email: registration@yetiforce.com (registration of the Software) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: a) Any file under this license must contain the content of the license or a link to the content of the license; b) The Software must, if technically possible, be registered with the Software Manufacturer using the built-in form or via e-mail as described on the Producer’s website. Each Entity that uses, configures or modifies the Software is subject to registration, regardless of whether it registers the Software for itself or on behalf of other entities. In the case of groups of people, i.e. an organization, company, family or any group of people, it is enough to register only a group of people by providing the data of the organization / company or data of one person from the family / group. If, despite many correct attempts to register the Software, there is no reply from the Producer, the Entity may generate the registration keys on its own; -c) Data used for registration must be true. All provided registration information, including the company’s name, can be used by YetiForce Sp. z o.o. (Ltd.) for marketing purposes (i.e. preparation of statistics, publication on the website). -YetiForce Sp. z o.o. (Ltd.) does not sell or transfer that data to other entities and guarantees confidentiality of personal data. +c) Data used for registration must be true. All provided registration information, including the company’s name, can be used by YetiForce S.A. (Ltd.) for marketing purposes (i.e. preparation of statistics, publication on the website). +YetiForce S.A. (Ltd.) does not sell or transfer that data to other entities and guarantees confidentiality of personal data. d) The content of the system footer, printouts and emails (including links and mechanisms controlling product registration and purchase of paid products) cannot be changed in the system, unless a written consent from the Producer is obtained or an official addon sold by the Producer is purchased, which allows the purchaser to modify the footer. The color of the footer can be changed as long as the footer content remains legible. e) In the case of products marked as paid, an appropriate license / subscription must be purchased from the Producer or an official Producer Partner; f) The entity using the Software is obligated to keep a history of changes introduced into the Software and, at the request of the Producer, enable an inspection to verify that the Entity complies with the terms of this license. The inspection may not take place more often than once every 3 years;
.php_cs.dist+9 −5 modified@@ -3,14 +3,16 @@ $config = \PhpCsFixer\Config::create() ->setRiskyAllowed(true) ->setIndent("\t") - ->setUsingCache(false) + ->setCacheFile(__DIR__ . '/.php-cs-fixer.cache') ->setRules([ - '@PHP56Migration' => true, - '@PHPUnit60Migration:risky' => true, + '@PHP74Migration' => true, + '@PHP74Migration:risky' => true, + '@PHP80Migration' => true, + '@PHP80Migration:risky' => true, '@PhpCsFixer' => true, '@PhpCsFixer:risky' => true, - 'list_syntax' => ['syntax' => 'short'], '@PSR2' => true, + 'list_syntax' => ['syntax' => 'short'], 'align_multiline_comment' => true, 'array_syntax' => ['syntax' => 'short'], 'blank_line_after_namespace' => true, @@ -27,6 +29,7 @@ $config = \PhpCsFixer\Config::create() ], 'explicit_string_variable' => false, 'declare_equal_normalize' => true, + 'declare_strict_types' => false, 'dir_constant' => false, 'doctrine_annotation_braces' => true, 'doctrine_annotation_indentation' => true, @@ -145,13 +148,14 @@ $config = \PhpCsFixer\Config::create() 'switch_case_space' => true, 'ternary_operator_spaces' => true, 'ternary_to_null_coalescing' => true, - 'trailing_comma_in_multiline_array' => false, + 'trailing_comma_in_multiline' => ['after_heredoc' => false, 'elements' => []], 'trim_array_spaces' => true, 'unary_operator_spaces' => true, 'visibility_required' => [ 'property', 'method', ], + 'void_return' => false, 'whitespace_after_comma_in_array' => true, ]) ->setFinder(PhpCsFixer\Finder::create()
README.md+18 −13 modified@@ -5,7 +5,7 @@ [](https://packagist.org/packages/yetiforce/yetiforce-crm)   -[](https://github.com/YetiForceCompany/YetiForceCRM/actions?query=workflow%3Atests) +[](https://github.com/YetiForceCompany/YetiForceCRM/actions?query=workflow%3Atests) [](https://sourceforge.net/projects/yetiforce/files/latest/download) [](https://GitHub.com/YetiForceCompany/YetiForceCRM/graphs/contributors/) [](https://crowdin.com/project/yetiforcecrm) @@ -22,6 +22,8 @@ [](https://observatory.mozilla.org/analyze/gitdeveloper.yetiforce.com) [](https://registry.hub.docker.com/r/yetiforce/yetiforcecrm/) +<img src="https://stats.yetiforce.com/matomo.php?idsite=4&rec=1" style="border:0" alt="" /> + <p align="center"> <a href='http://www.capterra.com/customer-relationship-management-software/reviews/159123/Yetiforce%20/YetiForce?utm_source=vendor&utm_medium=badge&utm_campaign=capterra_reviews_badge'> <img border='0' src='https://assets.capterra.com/badge/470cd214b89233aa4e89972fa49c3253.png?v=2111411&p=159123' /></a> <a href='https://www.capterra.com/customer-relationship-management-software/#affordable' width="50"><img border='0' src='https://public.yetiforce.com/img/CRM-AF-2017.png' width="150" /></a> @@ -48,7 +50,7 @@ </a> </p> -We design an innovative CRM system that is dedicated for large and medium sized companies. We dedicate it to everyone who values open source software, security and innovation. YetiForce was built on a rock-solid Vtiger foundation, but has hundreds of changes that help to accomplish even the most challenging tasks in the simplest way. Every function within the system was thought through and automated to ensure that all of them work together seamlessly and form a coherent integrity. We looked at the entire sales process and consequently refined the system, module by module. We have years of experience creating tailor made CRM software for a variety of different companies. Download it and have a first-hand experience. +We design an innovative CRM system that is dedicated to large and medium-sized companies. We dedicate it to everyone who values open source software, security, and innovation. YetiForce was built on a rock-solid Vtiger foundation but has hundreds of changes that help to accomplish even the most challenging tasks in the simplest way. Every function within the system was thought through and automated to ensure that all of them work together seamlessly and form coherent integrity. We looked at the entire sales process and consequently refined the system, module by module. We have years of experience creating tailor-made CRM software for a variety of different companies. Download it and have a first-hand experience. ## 😎 Demos @@ -149,14 +151,17 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ### Gallery: https://public.yetiforce.com/gallery - - - - - - - - - - - + + + + + + + + + + + + + +
.symfony.insight.yaml+1 −1 modified@@ -1,4 +1,4 @@ -php_version: 7.3 +php_version: 7.4 php_ini: | extension=imap.so
.yarnclean+152 −133 modified@@ -14,122 +14,9 @@ test.js CODE_OF_CONDUCT.md node_modules - # asset directories docs doc -chart.js/node_modules -chart.js/samples -chart.js/dist/Chart.bundle.js -chart.js/dist/Chart.bundle.min.js -chart.js/scripts -chart.js/src -chart.js/.htmllintrc - -#package -split.js/logo.svg -gantt-elastic/src -gantt-elastic/*.jpg -gantt-elastic/*.gif -updated-jqplot/optionsTutorial.txt -updated-jqplot/usage.txt -updated-jqplot/jqPlotCssStyling.txt -updated-jqplot/jqPlotOptions.txt -leaflet.markercluster/ISSUE_TEMPLATE.md -jQuery-Validation-Engine/releases.html -jQuery-Validation-Engine/runDemo.bat -jQuery-Validation-Engine/runDemo.sh -jQuery-Validation-Engine/js/jquery-1.8.2.min.js -jQuery-Validation-Engine/js/libs -jquery-gantt-editor/gantt.html -footable/icomoon -footable/js -footable/less -floatthead/src -blueimp-file-upload/node_modules -bootstrap-chosen/dist -bootstrap-datepicker/js -bootstrap-datepicker/less -bootstrap-daterangepicker/website -bootstrap-daterangepicker/drp.png -chartjs-plugin-funnel/spec -chartjs-plugin-funnel/config.jshintrc -clockpicker/assets -clockpicker/src -clockpicker/jquery.html -delegate/dist -@fortawesome/fontawesome-free/less -@fortawesome/fontawesome-free/scss -@fortawesome/fontawesome-free/sprites -@fortawesome/fontawesome-free/svgs -@fortawesome/fontawesome-free/js -@fortawesome/fontawesome-free/css/brands.css -@fortawesome/fontawesome-free/css/brands.min.css -@fortawesome/fontawesome-free/css/fontawesome.css -@fortawesome/fontawesome-free/css/fontawesome.min.css -@fortawesome/fontawesome-free/css/regular.css -@fortawesome/fontawesome-free/css/regular.min.css -@fortawesome/fontawesome-free/css/solid.css -@fortawesome/fontawesome-free/css/solid.min.css -@fortawesome/fontawesome-free/css/svg-with-js.css -@fortawesome/fontawesome-free/css/svg-with-js.min.css -@fortawesome/fontawesome-free/css/v4-shims.css -@fortawesome/fontawesome-free/css/v4-shims.min.css -good-listener/dist -html2canvas/flow-typed -jquery/external -jquery-lazy/plugins -jquery-outside-events/unit -jquery-outside-events/shared -jQuery-Validation-Engine/less -jstorage/debian -jstree-bootstrap-theme/dist/libs/ -jstree-bootstrap-theme/dist/.esformatter -jstree-bootstrap-theme/dist/jstree.js -jstree-bootstrap-theme/dist/jstree.min.js -jstree-bootstrap-theme/libs/bootstrap/js/bootstrap.js -jstree-bootstrap-theme/libs/jquery.js -jstree-bootstrap-theme/libs/bootstrap/js/bootstrap.min.js -leaflet.awesome-markers/screenshots -leaflet.markercluster/spec -mousetrap/plugins -perfect-scrollbar/types -popper.js/index.d.ts -popper.js/dist/esm -respond.js/src -respond.js/cross-domain -select2-theme-bootstrap4/dist -svg/svgBasic.html -svg/lion.svg - -hammerjs/.bowerrc -hammerjs/.jscsrc -html2canvas/dist/npm - -# removing unnecessary packages -updated-jqplot -css-line-break -delegate -good-listener -tiny-emitter -jquery-ui -jquery-ui-dist/external -asap -core-js -encoding -fbemitter -fbjs -iconv-lite -is-stream -isomorphic-fetch -js-tokens -loose-envify -node-fetch -object-assign -promise -safer-buffer -setimmediate -ua-parser-js # examples example @@ -203,74 +90,206 @@ MAINTAINING.md source build -#source - automatically generated +#removing unnecessary files in packages +@fortawesome/fontawesome-free/css/brands.css +@fortawesome/fontawesome-free/css/brands.min.css +@fortawesome/fontawesome-free/css/fontawesome.css +@fortawesome/fontawesome-free/css/fontawesome.min.css +@fortawesome/fontawesome-free/css/regular.css +@fortawesome/fontawesome-free/css/regular.min.css +@fortawesome/fontawesome-free/css/solid.css +@fortawesome/fontawesome-free/css/solid.min.css +@fortawesome/fontawesome-free/css/svg-with-js.css +@fortawesome/fontawesome-free/css/svg-with-js.min.css +@fortawesome/fontawesome-free/css/v4-font-face.css +@fortawesome/fontawesome-free/css/v4-font-face.min.css +@fortawesome/fontawesome-free/css/v4-shims.css +@fortawesome/fontawesome-free/css/v4-shims.min.css +@fortawesome/fontawesome-free/css/v5-font-face.css +@fortawesome/fontawesome-free/css/v5-font-face.min.css +@fortawesome/fontawesome-free/js +@fortawesome/fontawesome-free/less +@fortawesome/fontawesome-free/scss +@fortawesome/fontawesome-free/sprites +@fortawesome/fontawesome-free/svgs +@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.ttf +@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.woff2 add/src almond/src animate.css/src base64-arraybuffer/src block-ui/src blueimp-canvas-to-blob/src +blueimp-file-upload/node_modules blueimp-file-upload/src blueimp-load-image/src blueimp-tmpl/src -bootbox/src -bootstrap/src -bootstrap/js -bootstrap/dist/css +bootstrap-chosen/dist bootstrap-colorpicker/src +bootstrap-datepicker/js +bootstrap-datepicker/less bootstrap-datepicker/src +bootstrap-daterangepicker/drp.png +bootstrap-daterangepicker/moment.min.js bootstrap-daterangepicker/src +bootstrap-daterangepicker/website +bootstrap/dist/css +bootstrap/js +bootstrap/src +chart.js/.htmllintrc +chart.js/auto/ +chart.js/chunks/ +chart.js/dist/Chart.bundle.js +chart.js/dist/Chart.bundle.min.js +chart.js/helpers/ +chart.js/node_modules +chart.js/samples +chart.js/scripts/ +chart.js/src/ +chart.js/types/ chartjs-color-string/src chartjs-plugin-datalabels/src +chartjs-plugin-funnel/config.jshintrc +chartjs-plugin-funnel/spec chartjs-plugin-funnel/src chosen-js/src clipboard/src +clockpicker/assets +clockpicker/jquery.html +clockpicker/src color-name/src css-line-break/src -datatables.net/src datatables.net-bs4/src -datatables.net-responsive/src datatables.net-responsive-bs4/src +datatables.net-responsive/src +datatables.net/src +delegate/dist device-uuid/src dompurify/src +floatthead/src +footable/icomoon +footable/js +footable/less footable/src +fullcalendar/locales-all.js +fullcalendar/locales-all.min.js fullcalendar/src +fullcalendar/locales +gantt-elastic/*.gif +gantt-elastic/*.jpg +gantt-elastic/src +good-listener/dist +gridstack/dist/es5/ +gridstack/dist/gridstack-dd* +gridstack/dist/gridstack-engine* +gridstack/dist/gridstack-extra* +gridstack/dist/gridstack-jq* +gridstack/dist/gridstack-static* +gridstack/dist/gridstack.js +gridstack/dist/gridstack.js.map +gridstack/dist/h5/ +gridstack/dist/jq/ +gridstack/dist/src/ gridstack/src -hammerjs/src +html2canvas/dist/npm +html2canvas/flow-typed html2canvas/src html5shiv/src -inputmask/src -inputmask/dist/min inputmask/dist/inputmask -jquery/src +inputmask/dist/min +inputmask/src +jquery-gantt-editor/gantt.html jquery-hoverintent/src +jquery-lazy/plugins jquery-lazy/src jquery-mousewheel/src +jquery-outside-events/shared jquery-outside-events/src +jquery-outside-events/unit jquery-slimscroll/src jquery-ui-dist/src -jquery-ui-touch-punch/src +jQuery-Validation-Engine/js/jquery-1.8.2.min.js +jQuery-Validation-Engine/js/libs +jQuery-Validation-Engine/less +jQuery-Validation-Engine/releases.html +jQuery-Validation-Engine/runDemo.bat +jQuery-Validation-Engine/runDemo.sh +jquery/external +jquery/src +jstorage/debian jstorage/src -jstree/src +jstree-bootstrap-theme/dist/.esformatter +jstree-bootstrap-theme/dist/jstree.js +jstree-bootstrap-theme/dist/jstree.min.js +jstree-bootstrap-theme/dist/libs/ +jstree-bootstrap-theme/libs/bootstrap/js/bootstrap.js +jstree-bootstrap-theme/libs/bootstrap/js/bootstrap.min.js +jstree-bootstrap-theme/libs/jquery.js jstree-bootstrap-theme/src -leaflet/src -leaflet/dist/leaflet-src.js.map -leaflet/dist/leaflet-src.esm.js.map -leaflet/dist/leaflet-src.js -leaflet/dist/leaflet-src.esm.js +jstree/src +leaflet.awesome-markers/screenshots leaflet.awesome-markers/src +leaflet.markercluster/ISSUE_TEMPLATE.md +leaflet.markercluster/spec leaflet.markercluster/src -moment/src -moment/moment.js +leaflet/dist/leaflet-src.esm.js +leaflet/dist/leaflet-src.esm.js.map +leaflet/dist/leaflet-src.js +leaflet/dist/leaflet-src.js.map +leaflet/src +moment/dist moment/locale +moment/ts3.1-typings moment/min/locales.js moment/min/moment-with-locales.js moment/min/moment-with-locales.min.js +moment/min/moment-with-locales.min.js.map +moment/moment.js +moment/src +mousetrap/plugins mousetrap/src perfect-scrollbar/src +perfect-scrollbar/types +popper.js/dist/esm +popper.js/index.d.ts popper.js/src +respond.js/cross-domain +respond.js/src sass-material-colors/src +select2-theme-bootstrap4/dist select2/src +split.js/logo.svg split.js/src +svg/lion.svg +svg/svgBasic.html tiny-emitter/src +updated-jqplot/jqPlotCssStyling.txt +updated-jqplot/jqPlotOptions.txt +updated-jqplot/optionsTutorial.txt updated-jqplot/src +updated-jqplot/usage.txt + +# removing unnecessary packages +updated-jqplot +css-line-break +delegate +good-listener +tiny-emitter +jquery-ui +jquery-ui-dist/external +asap +core-js +encoding +fbemitter +fbjs +iconv-lite +is-stream +isomorphic-fetch +js-tokens +loose-envify +node-fetch +object-assign +promise +safer-buffer +setimmediate +ua-parser-js
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-jhxh-68jj-68c7ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-2890ghsaADVISORY
- github.com/yetiforcecompany/yetiforcecrm/commit/2c14baaf8dbc7fd82d5c585f2fa0c23528450618ghsax_refsource_MISCWEB
- huntr.dev/bounties/5d228a33-eda3-4cff-91da-7bc43e6636daghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.