VYPR
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.

PackageAffected versionsPatched versions
yetiforce/yetiforce-crmPackagist
< 6.4.06.4.0

Affected products

1

Patches

1
2c14baaf8dbc

YetiForce CRM ver. 6.4.0 (#16359)

https://github.com/yetiforcecompany/yetiforcecrmMariusz KrzaczkowskiAug 19, 2022via ghsa
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 @@
     [![Latest Stable Version](https://poser.pugx.org/yetiforce/yetiforce-crm/v/stable)](https://packagist.org/packages/yetiforce/yetiforce-crm)
     ![release date](https://img.shields.io/github/release-date/YetiForceCompany/YetiForceCRM)
     ![PHP Version](https://img.shields.io/packagist/php-v/yetiforce/yetiforce-crm)
    -[![Tested on PHP 7.3 to nightly](https://img.shields.io/badge/tested%20on-PHP%207.3%20|%207.4%20|%208.0%20-brightgreen.svg?maxAge=2419200)](https://github.com/YetiForceCompany/YetiForceCRM/actions?query=workflow%3Atests)
    +[![Tested on PHP 7.4 to nightly](https://img.shields.io/badge/tested%20on-PHP%207.4%20%7C%208.0%20%7C%208.1%20-brightgreen.svg?maxAge=2419200)](https://github.com/YetiForceCompany/YetiForceCRM/actions?query=workflow%3Atests)
     [![Download YetiForce CRM](https://img.shields.io/sourceforge/dt/yetiforce.svg)](https://sourceforge.net/projects/yetiforce/files/latest/download)
     [![GitHub contributors](https://img.shields.io/github/contributors/YetiForceCompany/YetiForceCRM.svg)](https://GitHub.com/YetiForceCompany/YetiForceCRM/graphs/contributors/)
     [![Crowdin](https://d322cqt584bo4o.cloudfront.net/yetiforcecrm/localized.svg)](https://crowdin.com/project/yetiforcecrm)
    @@ -22,6 +22,8 @@
     [![mozilla-observatory](https://img.shields.io/mozilla-observatory/grade/gitdeveloper.yetiforce.com?publish)](https://observatory.mozilla.org/analyze/gitdeveloper.yetiforce.com)
     [![Docker Hub](https://img.shields.io/badge/docker-ready-blue.svg)](https://registry.hub.docker.com/r/yetiforce/yetiforcecrm/)
     
    +<img src="https://stats.yetiforce.com/matomo.php?idsite=4&amp;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
     
    -![](https://public.yetiforce.com/img/main/1_Home_page.png)
    -
    -![](https://public.yetiforce.com/gallery/uploads/big/7679123c2d73f4065c9abc532d1bde77.png)
    -
    -![](https://public.yetiforce.com/img/main/3_Home_page.png)
    -
    -![](https://public.yetiforce.com/img/main/4_Calendar.png)
    -
    -![](https://public.yetiforce.com/img/main/8_List_Accounts.png)
    -
    -![](https://public.yetiforce.com/img/main/24_Detail_Projects_Gantt_Months.png)
    +![](https://yetiforce.com/images/v6/1_home.png)
    +![](https://yetiforce.com/images/v6/1_home2.png)
    +![](https://yetiforce.com/images/v6/1_home3.png)
    +![](https://yetiforce.com/images/v6/2_kanban1.png)
    +![](https://yetiforce.com/images/v6/2_kanban2.png)
    +![](https://yetiforce.com/images/v6/3_detail.png)
    +![](https://yetiforce.com/images/v6/3_edit.png)
    +![](https://yetiforce.com/images/v6/3_list.png)
    +![](https://yetiforce.com/images/v6/4_detail.png)
    +![](https://yetiforce.com/images/v6/5_perms.png)
    +![](https://yetiforce.com/images/v6/5_progreswizard.png)
    +![](https://yetiforce.com/images/v6/6_calendar.png)
    +![](https://yetiforce.com/images/v6/7_map.png)
    +![](https://yetiforce.com/images/v6/8_admin.png)
    
  • .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

News mentions

0

No linked articles in our index yet.