diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml
index 1869b179..5b9859ae 100644
--- a/.github/workflows/phpstan.yml
+++ b/.github/workflows/phpstan.yml
@@ -5,16 +5,39 @@ on:
name: PHPStan checks
jobs:
- phpstan:
- name: PHPStan
+ static-analysis:
+ name: "PHPStan"
+ runs-on: "ubuntu-latest"
- runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ php-version:
+ - "7.4"
+ - "8.0"
+ dependencies:
+ - "lowest"
+ - "highest"
steps:
- name: "Checkout"
- uses: actions/checkout@v2
+ uses: "actions/checkout@v2"
- - name: PHPStan
- uses: docker://oskarstark/phpstan-ga
+ - name: "Install PHP"
+ uses: "shivammathur/setup-php@v2"
with:
- args: analyse
\ No newline at end of file
+ coverage: "none"
+ php-version: "${{ matrix.php-version }}"
+ extensions: mbstring
+ tools: composer:v2
+
+ - name: "Install lowest dependencies"
+ if: ${{ matrix.dependencies == 'lowest' }}
+ run: "composer update --prefer-lowest --no-interaction --no-progress --no-suggest"
+
+ - name: "Install highest dependencies"
+ if: ${{ matrix.dependencies == 'highest' }}
+ run: "composer update --no-interaction --no-progress --no-suggest"
+
+ - name: "PHPStan"
+ run: "composer phpstan-analyse"
\ No newline at end of file
diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
index c0040183..f99825a2 100644
--- a/.github/workflows/phpunit.yml
+++ b/.github/workflows/phpunit.yml
@@ -33,8 +33,5 @@ jobs:
run: |
composer update ${{ env.COMPOSER_FLAGS }}
- - name: "Run tests"
- run: "composer exec phpunit -- --verbose"
-
- - name: Run test suite
- run: composer run-script unit-tests
\ No newline at end of file
+ - name: "run unit tests"
+ run: "composer phpunit-run-unit-tests"
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 0cff48d7..7c3db918 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ composer.lock
.phpunit.result.cache
tools/.env.local
tools/logs
-examples/logs
\ No newline at end of file
+examples/logs
+.env.local
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 652ff935..cc5d3991 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,17 +1,30 @@
# bitrix24-php-sdk change log
-## 2.0-alpha.4(25.11.2021)
+## 2.0-alpha.5 – 26.11.2021
+
+### Added
+
+* add method `countByFilter` for all related services, see
+ issue [Добавить для всех сущностей метод подсчёта количества элементов по фильтру #228](https://github.com/mesilov/bitrix24-php-sdk/issues/228)
+
+### Removed
+
+* remove all `0.*` and `1.*` code from `2.*` branch
+
+## 2.0-alpha.4 – 25.11.2021
### Changed
+
* switch `symfony/http-client` to `5.3` version requirement.
* switch `symfony/http-client-contracts` to `^2.4` version requirement.
* switch `symfony/event-dispatcher` to `5.3.*` version requirement.
* switch `ramsey/uuid` to `^4.0` version requirement.
-
+
### Fixed
+
* issue [Несовместимость с Laravel 8 #224](https://github.com/mesilov/bitrix24-php-sdk/issues/224)
-## 2.0-alpha.3(14.11.2021)
+## 2.0-alpha.3 – 14.11.2021
* add php8 version support
* change in scope «CRM» Product service and integration tests
@@ -22,7 +35,7 @@
* bump phpunit version
* bump phpstan version
-## 2.0-alpha.2 (31.01.2021)
+## 2.0-alpha.2 – 31.01.2021
* remove Travis CI and migrate to Github Actions
* add unit-tests in independent github action
@@ -37,7 +50,7 @@
* add in scope «IM» IM service and integration test
* add in default scope «Main» default service
-## 2.0-alpha.1 (11.07.2020)
+## 2.0-alpha.1 – 11.07.2020
* remove all v1 code
* migrate to Symfony HttpClient
@@ -46,6 +59,7 @@
* add Events support
## 0.1.0 (14.11.2021)
+
branch version 1.x – bugfix and security releases only
## 0.7.0 (11.07.2020)
diff --git a/README.md b/README.md
index 8d5f45a9..fc42448b 100644
--- a/README.md
+++ b/README.md
@@ -3,49 +3,62 @@ bitrix24-php-sdk [](https://packagist.org/packages/mesilov/bitrix24-php-sdk) [](https://packagist.org/packages/mesilov/bitrix24-php-sdk)
A powerful PHP library for the Bitrix24 REST API
+### BITRIX24-PHP-SDK Documentation
-[Bitrix24 API documentation - Russian](http://dev.1c-bitrix.ru/rest_help/)
-[Bitrix24 API documentation - English](https://training.bitrix24.com/rest_help/)
-[Register new Bitrix24 account](https://www.bitrix24.ru/create.php?p=255670)
+- [Russian](/docs/RU/documentation.md)
+- [English](/docs/EN/documentation.md)
-### SDK 2.0 core features
+### BITRIX24-PHP-SDK ✨FEATURES✨
-Bitrix24 auth features
+Support both auth modes:
-- ~~work with auth tokens~~
-- ~~work with incoming webhooks~~
+- [x] work with auth tokens for Bitrix24 applications in marketplace
+- [x] work with incoming webhooks for simple integration projects for current portal
-add low-level tools to devs:
+Low-level tools to devs:
-- ~~2.1 events (token expired, domain url changed)~~
-- 2.2 rate-limiter - wait for symfony/symfony#37471
-- 2.3 RetryHttpClient - symfony/symfony#38182
+- Domain core events:
+ - [x] Access Token expired
+ - [ ] Bitrix24 portal domain url changed
+- [ ] Rate-limit strategy
+- [ ] Retry strategy for safe methods
API - level features
-- ~~3.1 auto renew access tokens~~
-- 3.2 batch queries (work in progress)
-- ~~3.2.1 read~~
-- ~~3.2.2 write~~
-- 3.2.3 read + write
-- 3.2.4 read without count flag
-- 3.3 list queries with «start=-1» support
-- 3.4 offline queues
-- 3.5 add change domain URL support
-
-Core DTO
-
-- ~~Response~~
-- ~~Scope~~
-- ~~Time~~
-- ~~OAuthToken~~
-- ~~ApplicationProfile~~
-- ~~Pagination~~
-
-### SDK Documentation
-
-- [Russian](/docs/RU/documentation.md)
-- [English](/docs/EN/documentation.md)
+- [x] Auto renew access tokens
+- [ ] List queries with «start=-1» support
+- [ ] offline queues
+
+Performance improvements 🚀
+
+- Batch queries implemented with [PHP Generators](https://www.php.net/manual/en/language.generators.overview.php) – constant low memory and
+ low CPI usage
+ - [x] batch read data from bitrix24
+ - [x] batch write data to bitrix24
+ - [ ] write and read in one batch package
+ - [ ] composite batch queries to many entities (work in progress)
+- [ ] read without count flag
+
+### Development principles
+
+- Good developer experience
+ - auto-completion of methods at the IDE
+ - typed method call signatures
+ - typed results of method calls
+ - helpers for typical operations
+- Good documentation
+ - documentation on the operation of a specific method containing a link to the official documentation
+ - documentation for working with the SDK
+- Performance first:
+ - minimal impact on client code
+ - ability to work with large amounts of data with constant memory consumption
+ - efficient operation of the API using butch requests
+- Modern technology stack
+ - based on [Symfony HttpClient](https://symfony.com/doc/current/http_client.html)
+ - actual PHP versions language features
+- Reliable:
+ - test coverage: unit, integration, contract
+ - typical examples typical for different modes of operation and they are optimized for memory \ performance
### Architecture
@@ -94,11 +107,46 @@ Core DTO
Add `"mesilov/bitrix24-php-sdk": "2.x"` to `composer.json` of your application. Or clone repo to your project.
### Tests
+Tests locate in folder `tests` and we have two test types
+
+#### Unit tests
+**Fast**, in-memory tests without a network I\O
+For run unit tests you must call in command line
+
+```shell
+composer phpunit-run-unit-test
+```
+
+#### Integration tests
+**Slow** tests with full lifecycle with your **test** Bitrix24 portal via webhook.
+
+❗️Do not run integration tests with production portals ❗️
+
+For run integration test you must:
+1. Create [new Bitrix24 portal](https://www.bitrix24.ru/create.php?p=255670) for development tests
+2. Go to left menu, click «Sitemap»
+3. Find menu item «Developer resources»
+4. Click on menu item «Other»
+5. Click on menu item «Inbound webhook»
+6. Assign all permisions with webhook and click «save» button
+7. Create file `/tests/.env.local` with same settings, see comments in `/tests/.env` file.
+```yaml
+APP_ENV=dev
+BITRIX24_WEBHOOK=https:// your portal webhook url
+INTEGRATION_TEST_LOG_LEVEL=500
+```
+8. call in command line
+
+```shell
+composer composer phpunit-run-integration-tests
+```
-SDK test locate in folder `tests` and we have two test types
+#### PHP Static Analysis Tool – phpstan
+Call in command line
+```shell
+ composer phpstan-analyse
+```
-- Unit: **fast**, in-memory tests without a network I\O
-- Integration: **slow** tests with full lifecycle with test Bitrix24 portal via webhook
### Submitting bugs and feature requests
@@ -119,6 +167,14 @@ email:
### Sponsors
+### Documentation
+
+[Bitrix24 API documentation - Russian](http://dev.1c-bitrix.ru/rest_help/)
+
+[Bitrix24 API documentation - English](https://training.bitrix24.com/rest_help/)
+
+[Register new Bitrix24 account](https://www.bitrix24.ru/create.php?p=255670)
+
## Русский
### Принципы по которым ведётся разработка
diff --git a/composer.json b/composer.json
index 458fb99e..ad914b21 100644
--- a/composer.json
+++ b/composer.json
@@ -29,9 +29,9 @@
},
"require-dev": {
"monolog/monolog": "2.1.*",
- "symfony/console": "5.2.*",
- "symfony/dotenv": "5.2.*",
- "symfony/debug-bundle": "5.2.*",
+ "symfony/console": "5.3.*",
+ "symfony/dotenv": "5.3.*",
+ "symfony/debug-bundle": "5.3.*",
"phpstan/phpstan": "1.1.*",
"phpunit/phpunit": "9.5.*",
"roave/security-advisories": "dev-master"
@@ -48,8 +48,11 @@
}
},
"scripts": {
- "unit-tests": [
- "phpunit --colors=always --verbose"
+ "phpunit-run-unit-tests": [
+ "phpunit --testsuite unit_tests"
+ ],
+ "phpunit-run-integration-tests": [
+ "phpunit --testsuite integration_tests"
],
"phpstan-analyse": [
"vendor/bin/phpstan analyse"
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 31d2ac83..6856bc7f 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -1,7 +1,7 @@
parameters:
- level: 1
+ level: 5
paths:
- src/
- - tests/
+# - tests/
bootstrapFiles:
- tests/bootstrap.php
\ No newline at end of file
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 3d33e504..a3e33d9d 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -3,7 +3,7 @@
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
colors="true"
- bootstrap="vendor/autoload.php"
+ bootstrap="tests/bootstrap.php"
failOnRisky="true"
failOnWarning="true">
@@ -15,8 +15,11 @@
-
+
./tests/Unit
+
+ ./tests/Integration
+
diff --git a/src/Core/Batch.php b/src/Core/Batch.php
index 88b042ef..8b31fa14 100644
--- a/src/Core/Batch.php
+++ b/src/Core/Batch.php
@@ -476,7 +476,7 @@ public function getTraversable(bool $isHaltOnError): Generator
}
$nextItem = null;
- if ($resultNextItems !== null && array_key_exists($singleQueryKey, $resultNextItems) && count($resultNextItems) > 0) {
+ if ($resultNextItems !== null && array_key_exists($singleQueryKey, $resultNextItems)) {
$nextItem = $resultNextItems[$singleQueryKey];
}
@@ -544,7 +544,7 @@ private function convertToApiCommands(): array
$apiCommands = [];
foreach ($this->commands as $itemCommand) {
/**
- * @var $itemCommand Command
+ * @var Command $itemCommand
*/
$apiCommands[$itemCommand->getName() ?? $itemCommand->getUuid()->toString()] = sprintf(
'%s?%s',
diff --git a/src/Core/Credentials/AccessToken.php b/src/Core/Credentials/AccessToken.php
index 6600bcda..794d13a3 100644
--- a/src/Core/Credentials/AccessToken.php
+++ b/src/Core/Credentials/AccessToken.php
@@ -11,18 +11,9 @@
*/
class AccessToken
{
- /**
- * @var string
- */
- protected $accessToken;
- /**
- * @var string
- */
- protected $refreshToken;
- /**
- * @var int
- */
- protected $expires;
+ protected string $accessToken;
+ protected string $refreshToken;
+ protected int $expires;
/**
* AccessToken constructor.
@@ -73,7 +64,7 @@ public function hasExpired(): bool
/**
* @param array $request
*
- * @return static
+ * @return self
*/
public static function initFromArray(array $request): self
{
diff --git a/src/Core/Credentials/Credentials.php b/src/Core/Credentials/Credentials.php
index ed868228..8c8932d2 100644
--- a/src/Core/Credentials/Credentials.php
+++ b/src/Core/Credentials/Credentials.php
@@ -93,7 +93,7 @@ public function getAccessToken(): ?AccessToken
/**
* @param WebhookUrl $webhookUrl
*
- * @return static
+ * @return self
*/
public static function createForWebHook(WebhookUrl $webhookUrl): self
{
@@ -110,7 +110,7 @@ public static function createForWebHook(WebhookUrl $webhookUrl): self
* @param ApplicationProfile $applicationProfile
* @param string $domainUrl
*
- * @return static
+ * @return self
*/
public static function createForOAuth(AccessToken $accessToken, ApplicationProfile $applicationProfile, string $domainUrl): self
{
diff --git a/src/Core/Credentials/Scope.php b/src/Core/Credentials/Scope.php
index a7375659..f9b5d10f 100644
--- a/src/Core/Credentials/Scope.php
+++ b/src/Core/Credentials/Scope.php
@@ -71,8 +71,7 @@ class Scope
*/
public function __construct(array $scope = [])
{
- $scope = array_map('strtolower', $scope);
- array_unique($scope);
+ $scope = array_unique(array_map('strtolower', $scope));
foreach ($scope as $item) {
if (!in_array($item, $this->availableScope, true)) {
throw new UnknownScopeCodeException(sprintf('unknown application scope code - %s', $item));
diff --git a/src/Core/Response/DTO/RenewedAccessToken.php b/src/Core/Response/DTO/RenewedAccessToken.php
index 6623fd2e..a338c17a 100644
--- a/src/Core/Response/DTO/RenewedAccessToken.php
+++ b/src/Core/Response/DTO/RenewedAccessToken.php
@@ -14,34 +14,13 @@
*/
class RenewedAccessToken
{
- /**
- * @var AccessToken
- */
- private $accessToken;
- /**
- * @var Scope
- */
- private $scope;
- /**
- * @var string
- */
- private $memberId;
- /**
- * @var string
- */
- private $clientEndpoint;
- /**
- * @var string
- */
- private $serverEndpoint;
- /**
- * @var string
- */
- private $applicationStatus;
- /**
- * @var string
- */
- private $domain;
+ private AccessToken $accessToken;
+ private Scope $scope;
+ private string $memberId;
+ private string $clientEndpoint;
+ private string $serverEndpoint;
+ private string $applicationStatus;
+ private string $domain;
/**
* RenewedAccessToken constructor.
@@ -131,7 +110,7 @@ public function getDomain(): string
/**
* @param array $response
*
- * @return static
+ * @return self
* @throws \Bitrix24\SDK\Core\Exceptions\UnknownScopeCodeException
*/
public static function initFromArray(array $response): self
diff --git a/src/Core/Response/DTO/Time.php b/src/Core/Response/DTO/Time.php
index 8bd32305..3d41ec45 100644
--- a/src/Core/Response/DTO/Time.php
+++ b/src/Core/Response/DTO/Time.php
@@ -11,30 +11,12 @@
*/
class Time
{
- /**
- * @var float
- */
- protected $start;
- /**
- * @var float
- */
- protected $finish;
- /**
- * @var float
- */
- protected $duration;
- /**
- * @var float
- */
- protected $processing;
- /**
- * @var \DateTimeImmutable
- */
- protected $dateStart;
- /**
- * @var \DateTimeImmutable
- */
- protected $dateFinish;
+ protected float $start;
+ protected float $finish;
+ protected float $duration;
+ protected float $processing;
+ protected \DateTimeImmutable $dateStart;
+ protected \DateTimeImmutable $dateFinish;
/**
* Time constructor.
@@ -113,7 +95,7 @@ public function getDateFinish(): \DateTimeImmutable
/**
* @param array $response
*
- * @return static
+ * @return self
* @throws \Exception
*/
public static function initFromResponse(array $response): self
diff --git a/src/Services/CRM/Deal/Service/Deal.php b/src/Services/CRM/Deal/Service/Deal.php
index c8289157..fac6432e 100644
--- a/src/Services/CRM/Deal/Service/Deal.php
+++ b/src/Services/CRM/Deal/Service/Deal.php
@@ -249,4 +249,54 @@ public function update(int $id, array $fields, array $params): UpdatedItemResult
)
);
}
+
+ /**
+ * Count deals by filter
+ *
+ * @param array{
+ * ID?: int,
+ * TITLE?: string,
+ * TYPE_ID?: string,
+ * CATEGORY_ID?: string,
+ * STAGE_ID?: string,
+ * STAGE_SEMANTIC_ID?: string,
+ * IS_NEW?: string,
+ * IS_RECURRING?: string,
+ * PROBABILITY?: string,
+ * CURRENCY_ID?: string,
+ * OPPORTUNITY?: string,
+ * IS_MANUAL_OPPORTUNITY?: string,
+ * TAX_VALUE?: string,
+ * LEAD_ID?: string,
+ * COMPANY_ID?: string,
+ * CONTACT_ID?: string,
+ * QUOTE_ID?: string,
+ * BEGINDATE?: string,
+ * CLOSEDATE?: string,
+ * OPENED?: string,
+ * CLOSED?: string,
+ * COMMENTS?: string,
+ * ADDITIONAL_INFO?: string,
+ * LOCATION_ID?: string,
+ * IS_RETURN_CUSTOMER?: string,
+ * IS_REPEATED_APPROACH?: string,
+ * SOURCE_ID?: string,
+ * SOURCE_DESCRIPTION?: string,
+ * ORIGINATOR_ID?: string,
+ * ORIGIN_ID?: string,
+ * UTM_SOURCE?: string,
+ * UTM_MEDIUM?: string,
+ * UTM_CAMPAIGN?: string,
+ * UTM_CONTENT?: string,
+ * UTM_TERM?: string
+ * } $filter
+ *
+ * @return int
+ * @throws \Bitrix24\SDK\Core\Exceptions\BaseException
+ * @throws \Bitrix24\SDK\Core\Exceptions\TransportException
+ */
+ public function countByFilter(array $filter = []): int
+ {
+ return $this->list([], $filter, ['ID'], 1)->getCoreResponse()->getResponseData()->getPagination()->getTotal();
+ }
}
\ No newline at end of file
diff --git a/src/Services/CRM/Product/Service/Batch.php b/src/Services/CRM/Product/Service/Batch.php
index 1fc755f4..ee553c60 100644
--- a/src/Services/CRM/Product/Service/Batch.php
+++ b/src/Services/CRM/Product/Service/Batch.php
@@ -21,10 +21,11 @@ class Batch extends AbstractBatchService
* batch list method
*
* @param array{
- * ID?: int,
+ * ID?: int
+ * } $order
*
* @param array{
- * ID?: int,
+ * ID?: int
* } $filter
* @param array $select = ['ID','CATALOG_ID','PRICE','CURRENCY_ID','NAME','CODE','DESCRIPTION','DESCRIPTION_TYPE','ACTIVE','SECTION_ID','SORT','VAT_ID','VAT_INCLUDED','MEASURE','XML_ID','PREVIEW_PICTURE','DETAIL_PICTURE','DATE_CREATE','TIMESTAMP_X','MODIFIED_BY','CREATED_BY']
* @param int|null $limit
diff --git a/src/Services/CRM/Product/Service/Product.php b/src/Services/CRM/Product/Service/Product.php
index 9a725eda..1a94f095 100644
--- a/src/Services/CRM/Product/Service/Product.php
+++ b/src/Services/CRM/Product/Service/Product.php
@@ -211,4 +211,40 @@ public function update(int $id, array $fields): UpdatedItemResult
)
);
}
+
+ /**
+ * Count products by filter
+ *
+ * @param array{
+ * ID?: int,
+ * CATALOG_ID?: int,
+ * PRICE?: string,
+ * CURRENCY_ID?: string,
+ * NAME?: string,
+ * CODE?: string,
+ * DESCRIPTION?: string,
+ * DESCRIPTION_TYPE?: string,
+ * ACTIVE?: string,
+ * SECTION_ID?: int,
+ * SORT?: int,
+ * VAT_ID?: int,
+ * VAT_INCLUDED?: string,
+ * MEASURE?: int,
+ * XML_ID?: string,
+ * PREVIEW_PICTURE?: string,
+ * DETAIL_PICTURE?: string,
+ * DATE_CREATE?: string,
+ * TIMESTAMP_X?: string,
+ * MODIFIED_BY?: int,
+ * CREATED_BY?: int
+ * } $filter
+ *
+ * @return int
+ * @throws \Bitrix24\SDK\Core\Exceptions\BaseException
+ * @throws \Bitrix24\SDK\Core\Exceptions\TransportException
+ */
+ public function countByFilter(array $filter = []): int
+ {
+ return $this->list([], $filter, ['ID'], 1)->getCoreResponse()->getResponseData()->getPagination()->getTotal();
+ }
}
\ No newline at end of file
diff --git a/src/bitrix24.php b/src/bitrix24.php
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/classes/crm/company/userfield.php b/src/classes/crm/company/userfield.php
deleted file mode 100644
index 2b9eb435..00000000
--- a/src/classes/crm/company/userfield.php
+++ /dev/null
@@ -1,97 +0,0 @@
-client->call(
- 'crm.company.userfield.list',
- array(
- 'order' => $order,
- 'filter'=> $filter
- )
- );
- return $fullResult;
- }
-
- /**
- * Get item userfield
- * @link https://dev.1c-bitrix.ru/rest_help/crm/company/crm_company_userfield_get.php
- * @param integer $userfieldId - company userfield id
- * @return array
- */
- public function get($userfieldId)
- {
- $fullResult = $this->client->call(
- 'crm.company.userfield.get',
- array('id' => $userfieldId)
- );
- return $fullResult;
- }
-
- /**
- * Delete userfield
- * @link https://dev.1c-bitrix.ru/rest_help/crm/company/crm_company_userfield_delete.php
- * @param integer $userfieldId - company userfield id
- * @return array
- */
- public function delete($userfieldId)
- {
- $fullResult = $this->client->call(
- 'crm.company.userfield.delete',
- array('id' => $userfieldId)
- );
- return $fullResult;
- }
-
- /**
- * Add a new userfield to company
- * @param array $fields array of fields
- * @link https://dev.1c-bitrix.ru/rest_help/crm/company/crm_company_userfield_add.php
- * @return array
- */
- public function add($fields = array())
- {
- $fullResult = $this->client->call(
- 'crm.company.userfield.add',
- array('fields' => $fields)
- );
- return $fullResult;
- }
-
-
- /**
- * Updates userfield
- *
- * @param $id
- * @param array $fields
- *
- * @link https://dev.1c-bitrix.ru/rest_help/crm/company/crm_company_userfield_update.php
- * @return array
- */
- public function update($id, $fields = array())
- {
- $fullResult = $this->client->call(
- 'crm.company.userfield.update',
- array(
- 'id' => $id,
- 'fields' => $fields
- )
- );
-
- return $fullResult;
- }
-}
diff --git a/src/classes/crm/contact/contact.php b/src/classes/crm/contact/contact.php
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/classes/crm/product/property.php b/src/classes/crm/product/property.php
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/classes/user/user.php b/src/classes/user/user.php
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/.env b/tests/.env
new file mode 100644
index 00000000..fb14da23
--- /dev/null
+++ b/tests/.env
@@ -0,0 +1,21 @@
+# In all environments, the following files are loaded if they exist,
+# the latter taking precedence over the former:
+#
+# * .env contains default values for the environment variables needed by the app
+# * .env.local uncommitted file with local overrides
+# * .env.$APP_ENV committed environment-specific defaults
+# * .env.$APP_ENV.local uncommitted environment-specific overrides
+#
+# Real environment variables win over .env files.
+#
+# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
+#
+# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
+# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
+
+# For run integration tests you must create incoming webhook for YOUR bitrix24 portal and create .env.local file with same settings
+
+APP_ENV=dev
+BITRIX24_WEBHOOK=
+# monolog log level
+INTEGRATION_TEST_LOG_LEVEL=
\ No newline at end of file
diff --git a/tests/Integration/Fabric.php b/tests/Integration/Fabric.php
new file mode 100644
index 00000000..b808b82f
--- /dev/null
+++ b/tests/Integration/Fabric.php
@@ -0,0 +1,40 @@
+pushHandler(new StreamHandler(STDOUT, (int)$_ENV['INTEGRATION_TEST_LOG_LEVEL']));
+ $log->pushProcessor(new \Monolog\Processor\MemoryUsageProcessor(true, true));
+ $log->pushProcessor(new \Monolog\Processor\IntrospectionProcessor());
+ $log->debug('==============================================================');
+
+ $core = (new CoreBuilder())
+ ->withLogger($log)
+ ->withWebhookUrl($_ENV['BITRIX24_WEBHOOK'])
+ ->build();
+ $batch = new Batch($core, $log);
+
+ return new ServiceBuilder($core, $batch, $log);
+ }
+}
\ No newline at end of file
diff --git a/tests/Integration/Services/CRM/Deal/Service/DealTest.php b/tests/Integration/Services/CRM/Deal/Service/DealTest.php
index 356183fa..fc9b853c 100644
--- a/tests/Integration/Services/CRM/Deal/Service/DealTest.php
+++ b/tests/Integration/Services/CRM/Deal/Service/DealTest.php
@@ -115,6 +115,31 @@ public function testBatchAdd(): void
self::assertEquals(count($deals), $cnt);
}
+ /**
+ * @throws \Bitrix24\SDK\Core\Exceptions\BaseException
+ * @throws \Bitrix24\SDK\Core\Exceptions\TransportException
+ * @covers \Bitrix24\SDK\Services\CRM\Deal\Service\Deal::countByFilter
+ */
+ public function testCountByFilter(): void
+ {
+ $before = $this->dealService->countByFilter();
+
+ $newDealsCount = 60;
+ $deals = [];
+ for ($i = 1; $i <= $newDealsCount; $i++) {
+ $deals[] = ['TITLE' => 'TITLE-' . $i];
+ }
+ $cnt = 0;
+ foreach ($this->dealService->batch->add($deals) as $item) {
+ $cnt++;
+ }
+ self::assertEquals(count($deals), $cnt);
+
+ $after = $this->dealService->countByFilter();
+
+ $this->assertEquals($before + $newDealsCount, $after);
+ }
+
public function setUp(): void
{
$this->dealService = Fabric::getServiceBuilder()->getCRMScope()->deal();
diff --git a/tests/Integration/Services/CRM/Products/Service/ProductsTest.php b/tests/Integration/Services/CRM/Products/Service/ProductsTest.php
index b58f0ea4..0e9223ba 100644
--- a/tests/Integration/Services/CRM/Products/Service/ProductsTest.php
+++ b/tests/Integration/Services/CRM/Products/Service/ProductsTest.php
@@ -123,6 +123,30 @@ public function testBatchAdd(): void
self::assertEquals(count($products), $cnt);
}
+ /**
+ * @throws \Bitrix24\SDK\Core\Exceptions\BaseException
+ * @throws \Bitrix24\SDK\Core\Exceptions\TransportException
+ * @covers \Bitrix24\SDK\Services\CRM\Product\Service\Product::countByFilter
+ */
+ public function testCountByFilter(): void
+ {
+ $productsCountBefore = $this->productService->countByFilter();
+ $newProductsCount = 60;
+ $products = [];
+ for ($i = 1; $i <= $newProductsCount; $i++) {
+ $products[] = ['NAME' => 'NAME-' . $i];
+ }
+ $cnt = 0;
+ foreach ($this->productService->batch->add($products) as $item) {
+ $cnt++;
+ }
+
+ self::assertEquals(count($products), $cnt);
+
+ $productsCountAfter = $this->productService->countByFilter();
+ $this->assertEquals($productsCountBefore + $newProductsCount, $productsCountAfter);
+ }
+
public function setUp(): void
{
$this->productService = Fabric::getServiceBuilder()->getCRMScope()->product();
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 0588c285..0e854a6b 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -2,4 +2,22 @@
declare(strict_types=1);
-require_once \dirname(__DIR__) . '/vendor/autoload.php';
+use Symfony\Component\Console\Input\ArgvInput;
+use Symfony\Component\Dotenv\Dotenv;
+
+require_once dirname(__DIR__) . '/vendor/autoload.php';
+
+if (!class_exists(Dotenv::class)) {
+ throw new LogicException('You need to add "symfony/dotenv" as Composer dependencies.');
+}
+
+$input = new ArgvInput();
+if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) {
+ putenv('APP_ENV=' . $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
+}
+
+if ($input->hasParameterOption('--no-debug', true)) {
+ putenv('APP_DEBUG=' . $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
+}
+
+(new Dotenv())->loadEnv(dirname(__DIR__).'/tests/.env');
\ No newline at end of file