From 761505dbfff25ed3d3569ee9bec2534403a1fd03 Mon Sep 17 00:00:00 2001 From: "a.pushkarev" Date: Sun, 29 May 2022 16:30:26 +0500 Subject: [PATCH] Version 2.0.0 --- .gitignore | 22 +- LICENSE | 4 +- README.md | 241 +++++++++------- composer.json | 14 +- example/logger.php | 28 ++ example/proxy.php | 17 ++ example/visitors.php | 14 + examples/customQuery.php | 20 -- examples/getAgeGender.php | 15 - examples/getBrowsers.php | 15 - examples/getGeo.php | 15 - examples/getMostViewedPages.php | 15 - examples/getPreset.php | 15 - examples/getUsersSearchEngine.php | 15 - examples/getVisitors.php | 15 - src/Client.php | 60 ++++ src/Exception/ClientException.php | 14 + src/Exception/FormatException.php | 14 + src/Exceptions/YaMetrikaException.php | 17 -- src/Response.php | 68 +++++ src/YaMetrika.php | 396 ++++---------------------- 21 files changed, 436 insertions(+), 598 deletions(-) create mode 100644 example/logger.php create mode 100644 example/proxy.php create mode 100644 example/visitors.php delete mode 100644 examples/customQuery.php delete mode 100644 examples/getAgeGender.php delete mode 100644 examples/getBrowsers.php delete mode 100644 examples/getGeo.php delete mode 100644 examples/getMostViewedPages.php delete mode 100644 examples/getPreset.php delete mode 100644 examples/getUsersSearchEngine.php delete mode 100644 examples/getVisitors.php create mode 100644 src/Client.php create mode 100644 src/Exception/ClientException.php create mode 100644 src/Exception/FormatException.php delete mode 100644 src/Exceptions/YaMetrikaException.php create mode 100644 src/Response.php diff --git a/.gitignore b/.gitignore index b38e610..2692ae0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,19 @@ -.idea/ -vendor/ -examples/config.php +# Logs +logs +*.log + +.env composer.phar -composer.lock \ No newline at end of file +composer.lock +vendor + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/LICENSE b/LICENSE index cb91952..0cfda8c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017 Alexander Pushkarev +Copyright (c) 2022 Alexander Pushkarev 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 @@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index fe01735..9312414 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Библиотека для удобного взаимодействия с Yandex Metrika API [![Latest Stable Version](https://poser.pugx.org/axp-dev/ya-metrika/v/stable)](https://packagist.org/packages/axp-dev/ya-metrika) -[![Latest Unstable Version](https://poser.pugx.org/axp-dev/ya-metrika/v/unstable)](https://packagist.org/packages/axp-dev/ya-metrika) +[![PHP Version Require](http://poser.pugx.org/axp-dev/ya-metrika/require/php)](https://packagist.org/packages/axp-dev/ya-metrika) [![License](https://poser.pugx.org/axp-dev/ya-metrika/license)](https://packagist.org/packages/axp-dev/ya-metrika) ## Оглавление @@ -10,6 +10,7 @@ + [Composer](#Установка-через-composer) + [Получение токена](#Получение-токена) + [Инициализация](#Инициализация) + + [Примеры](#Примеры) 2. [Использование](#Использование) + [Данные по посещаемости](#Данные-по-посещаемости) + [Самые просматриваемые страницы](#Самые-просматриваемые-страницы) @@ -17,10 +18,14 @@ + [Пользователи из поисковых систем](#Пользователи-из-поисковых-систем) + [Пользователи по странам и регионам](#Пользователи-по-странам-и-регионам) + [Пол и возраст пользователей](#Пол-и-возраст-пользователей) + + [Поисковые фразы](#Поисковые-фразы) + [Данные по шаблону](#Данные-по-шаблону) + [Произвольный запрос](#Произвольный-запрос) -3. [Автор](#Автор) -4. [Лицензия](#Лицензия) +3. [Ответ](#Ответ) + + [Чистые данные](#Чистые-данные) + + [Отформатированные данные](#Отформатированные-данные) +4. [Автор](#Автор) +5. [Лицензия](#Лицензия) ## Старт ### Установка через composer @@ -38,182 +43,204 @@ $ composer require axp-dev/ya-metrika ### Инициализация ```php -$token = ''; -$counter_id = ''; -$YaMetrika = new YaMetrika($token, $counter_id); - -// Пример использования без форматирвоания -$traffic = $YaMetrika->getPreset('traffic') - ->data; - -// Пример использования с форматированием -$traffic = $YaMetrika->getPreset('traffic', 30, 15) - ->format() - ->formatData; - -// Пример произвольного запроса -$data = [ - 'date1' => Carbon::yesterday()->format('Y-m-d'), - 'date2' => Carbon::today()->format('Y-m-d'), - 'metrics' => 'ym:s:visits', -]; -$visits = $YaMetrika->customQuery($data) - ->data; +$token = getenv('TOKEN'); +$counterId = getenv('COUNTER_ID'); + +$client = new Client($token, $counterId); +$metrika = new YaMetrika($client); ``` + +### Примеры ++ [Данные о посещаемости](https://github.com/axp-dev/ya-metrika/blob/master/example/visitors.php) ++ [Логирование запросов](https://github.com/axp-dev/ya-metrika/blob/master/example/logger.php) ++ [Использование Proxy](https://github.com/axp-dev/ya-metrika/blob/master/example/proxy.php) + ## Использование -Для форматирования данных необходимо вызвать `format()`. Для произвольных запросов данный метод также работает. ### Данные по посещаемости Будут получены данные: визитов, просмотров, уникальных посетителей по дням. #### За последние N дней ```php -public function getVisitors($days = 30) : self +public function getVisitors(int $days = 30): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$days | integer | Кол-во дней. По умолчанию 30 +| Название | Тип | Описание | +|----------|---------|------------------------------| +| $days | integer | Кол-во дней. По умолчанию 30 | #### За указанный период ```php -public function getVisitorsForPeriod(DateTime $startDate, DateTime $endDate) : self +public function getVisitorsForPeriod(DateTime $startDate, DateTime $endDate): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$startDate | DateTime | Начальная дата -$endDate | DateTime | Конечная дата +| Название | Тип | Описание | +|------------|----------|----------------| +| $startDate | DateTime | Начальная дата | +| $endDate | DateTime | Конечная дата | ### Самые просматриваемые страницы #### За последние N дней ```php -public function getMostViewedPages($days = 30, $limit = 10) : self +public function getMostViewedPages(int $days = 30, int $limit = 10): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$days | integer | Кол-во дней. По умолчанию 30 -$limit | integer | Лимит записей. По умолчанию 10 +| Название | Тип | Описание | +|----------|---------|--------------------------------| +| $days | integer | Кол-во дней. По умолчанию 30 | +| $limit | integer | Лимит записей. По умолчанию 10 | #### За указанный период ```php -public function getMostViewedPagesForPeriod(DateTime $startDate, DateTime $endDate, $limit = 10) : self +public function getMostViewedPagesForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 10): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$startDate | DateTime | Начальная дата -$endDate | DateTime | Конечная дата -$limit | integer | Лимит записей. По умолчанию 10 +| Название | Тип | Описание | +|------------|----------|--------------------------------| +| $startDate | DateTime | Начальная дата | +| $endDate | DateTime | Конечная дата | +| $limit | integer | Лимит записей. По умолчанию 10 | ### Браузеры пользователей #### За последние N дней ```php -public function getBrowsers($days = 30, $limit = 10) : self +public function getBrowsers(int $days = 30, int $limit = 10): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$days | integer | Кол-во дней. По умолчанию 30 -$limit | integer | Лимит записей. По умолчанию 10 +| Название | Тип | Описание | +|----------|---------|--------------------------------| +| $days | integer | Кол-во дней. По умолчанию 30 | +| $limit | integer | Лимит записей. По умолчанию 10 | #### За указанный период ```php -public function getBrowsersForPeriod(DateTime $startDate, DateTime $endDate, $limit = 10) : self +public function getBrowsersForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 10): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$startDate | DateTime | Начальная дата -$endDate | DateTime | Конечная дата -$limit | integer | Лимит записей. По умолчанию 10 +| Название | Тип | Описание | +|------------|----------|--------------------------------| +| $startDate | DateTime | Начальная дата | +| $endDate | DateTime | Конечная дата | +| $limit | integer | Лимит записей. По умолчанию 10 | ### Пользователи из поисковых систем #### За последние N дней ```php -public function getUsersSearchEngine($days = 30, $limit = 10) : self +public function getUsersSearchEngine(int $days = 30, int $limit = 10): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$days | integer | Кол-во дней. По умолчанию 30 -$limit | integer | Лимит записей. По умолчанию 10 +| Название | Тип | Описание | +|----------|---------|--------------------------------| +| $days | integer | Кол-во дней. По умолчанию 30 | +| $limit | integer | Лимит записей. По умолчанию 10 | #### За указанный период ```php -public function getUsersSearchEngineForPeriod(DateTime $startDate, DateTime $endDate, $limit = 10) : self +public function getUsersSearchEngineForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 10): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$startDate | DateTime | Начальная дата -$endDate | DateTime | Конечная дата -$limit | integer | Лимит записей. По умолчанию 10 +| Название | Тип | Описание | +|------------|----------|--------------------------------| +| $startDate | DateTime | Начальная дата | +| $endDate | DateTime | Конечная дата | +| $limit | integer | Лимит записей. По умолчанию 10 | ### Пользователи по странам и регионам #### За последние N дней ```php -public function getGeo($days = 7, $limit = 20) : self +public function getGeo($days = 7, $limit = 20): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$days | integer | Кол-во дней. По умолчанию 7 -$limit | integer | Лимит записей. По умолчанию 20 +| Название | Тип | Описание | +|----------|---------|--------------------------------| +| $days | integer | Кол-во дней. По умолчанию 7 | +| $limit | integer | Лимит записей. По умолчанию 20 | #### За указанный период ```php -public function getGeoForPeriod(DateTime $startDate, DateTime $endDate, $limit = 20) : self +public function getGeoForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 20): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$startDate | DateTime | Начальная дата -$endDate | DateTime | Конечная дата -$limit | integer | Лимит записей. По умолчанию 20 +| Название | Тип | Описание | +|------------|----------|--------------------------------| +| $startDate | DateTime | Начальная дата | +| $endDate | DateTime | Конечная дата | +| $limit | integer | Лимит записей. По умолчанию 20 | ### Пол и возраст пользователей #### За последние N дней ```php -public function getAgeGender($days = 30, $limit = 20) : self +public function getAgeGender($days = 30, $limit = 20): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$days | integer | Кол-во дней. По умолчанию 30 -$limit | integer | Лимит записей. По умолчанию 20 +| Название | Тип | Описание | +|----------|---------|--------------------------------| +| $days | integer | Кол-во дней. По умолчанию 30 | +| $limit | integer | Лимит записей. По умолчанию 20 | #### За указанный период ```php -public function getAgeGenderForPeriod(DateTime $startDate, DateTime $endDate, $limit = 20) : self +public function getAgeGenderForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 20): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$startDate | DateTime | Начальная дата -$endDate | DateTime | Конечная дата -$limit | integer | Лимит записей. По умолчанию 20 +| Название | Тип | Описание | +|------------|----------|--------------------------------| +| $startDate | DateTime | Начальная дата | +| $endDate | DateTime | Конечная дата | +| $limit | integer | Лимит записей. По умолчанию 20 | + +### Поисковые фразы +#### За последние N дней +```php +public function getSearchPhrases($days = 30, $limit = 20): Response +``` +| Название | Тип | Описание | +|----------|---------|--------------------------------| +| $days | integer | Кол-во дней. По умолчанию 30 | +| $limit | integer | Лимит записей. По умолчанию 20 | + +#### За указанный период +```php +public function getSearchPhrasesForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 20): Response +``` +| Название | Тип | Описание | +|------------|----------|--------------------------------| +| $startDate | DateTime | Начальная дата | +| $endDate | DateTime | Конечная дата | +| $limit | integer | Лимит записей. По умолчанию 20 | ### Данные по шаблону -Шаблоны (preset) автоматически задают метрики и группировки, которые необходимы для того или иного отчета. +Шаблоны (preset) автоматически задают метрики и группировки, которые необходимы для того или иного отчета. Список всех шаблонов доступен по ссылке - [tech.yandex.ru/metrika/../presets-docpage](https://tech.yandex.ru/metrika/doc/api2/api_v1/presets/presets-docpage/). #### За последние N дней ```php -public function getPreset($template, $days = 30, $limit = 10) : self +public function getPreset(string $preset, int $days = 30, int $limit = 10): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$template | string | Название шаблона -$days | integer | Кол-во дней. По умолчанию 30 -$limit | integer | Лимит записей. По умолчанию 10 +| Название | Тип | Описание | +|----------|---------|--------------------------------| +| $preset | string | Название шаблона | +| $days | integer | Кол-во дней. По умолчанию 30 | +| $limit | integer | Лимит записей. По умолчанию 10 | #### За указанный период ```php -public function getPresetForPeriod($template, DateTime $startDate, DateTime $endDate, $limit = 10) : self +public function getPresetForPeriod(string $preset, DateTime $startDate, DateTime $endDate, int $limit = 10): Response ``` -Название | Тип | Описание ----------|-----|---------------------- -$template | string | Название шаблона -$startDate | DateTime | Начальная дата -$endDate | DateTime | Конечная дата -$limit | integer | Лимит записей. По умолчанию 10 +| Название | Тип | Описание | +|------------|----------|--------------------------------| +| $preset | string | Название шаблона | +| $startDate | DateTime | Начальная дата | +| $endDate | DateTime | Конечная дата | +| $limit | integer | Лимит записей. По умолчанию 10 | ### Произвольный запрос Параметры `ids` и `oauth_token` передавать не нужно. ```php -public function customQuery($params) : self +public function customQuery(array $params): Response +``` +| Название | Тип | Описание | +|----------|-------|-------------------| +| $params | array | Параметры запроса | + +## Ответ +### Чистые данные +Возвращает исходные данные, которые были получены напрямую из api. +```php +public function rawData(): array +``` + +### Отформатированные данные +Возвращает отформатированные данные. Будут переименованы поля, удалены ненужные префиксы. +```php +public function formatData(): array ``` -Название | Тип | Описание ----------|-----|---------------------- -$params | array | Параметры запроса ## Автор [Alexander Pushkarev](https://github.com/axp-dev), e-mail: [axp-dev@yandex.com](mailto:axp-dev@yandex.com) diff --git a/composer.json b/composer.json index 58bbdd9..8b6981d 100644 --- a/composer.json +++ b/composer.json @@ -2,8 +2,8 @@ "name": "axp-dev/ya-metrika", "description": "Yandex Metrika API Library", "homepage": "https://github.com/axp-dev/ya-metrika", - "keywords": ["yandex","metrika","api"], - "version": "1.1.0", + "keywords": ["yandex", "metrika", "api"], + "version": "2.0.0", "license": "MIT", "authors": [ { @@ -13,9 +13,11 @@ } ], "require": { - "php": ">=5.6.4", - "guzzlehttp/guzzle": "^6.3|^7.0", - "nesbot/carbon": "^1.22|^2.0" + "php": ">=8.0", + "guzzlehttp/guzzle": "^7.4.3" + }, + "require-dev": { + "monolog/monolog": "^2.6.0" }, "autoload": { "psr-4": { @@ -23,4 +25,4 @@ } }, "minimum-stability": "dev" -} +} \ No newline at end of file diff --git a/example/logger.php b/example/logger.php new file mode 100644 index 0000000..749d500 --- /dev/null +++ b/example/logger.php @@ -0,0 +1,28 @@ +push( + Middleware::log( + new Logger('Logger'), + new MessageFormatter('{req_body} - {res_body}') + ) +); + +$token = getenv('TOKEN'); +$counterId = getenv('COUNTER_ID'); + +$client = new Client($token, $counterId, [ + 'handler' => $stack +]); +$metrika = new YaMetrika($client); + +$visitors = $metrika->getVisitors(); + +print_r($visitors->formatData()); \ No newline at end of file diff --git a/example/proxy.php b/example/proxy.php new file mode 100644 index 0000000..045d4b3 --- /dev/null +++ b/example/proxy.php @@ -0,0 +1,17 @@ + $proxy +]); +$metrika = new YaMetrika($client); + +$visitors = $metrika->getVisitors(); + +print_r($visitors->formatData()); \ No newline at end of file diff --git a/example/visitors.php b/example/visitors.php new file mode 100644 index 0000000..2ce7ba1 --- /dev/null +++ b/example/visitors.php @@ -0,0 +1,14 @@ +getVisitors(); + +print_r($visitors->formatData()); \ No newline at end of file diff --git a/examples/customQuery.php b/examples/customQuery.php deleted file mode 100644 index 2a33bde..0000000 --- a/examples/customQuery.php +++ /dev/null @@ -1,20 +0,0 @@ - Carbon\Carbon::yesterday()->format('Y-m-d'), - 'date2' => Carbon\Carbon::today()->format('Y-m-d'), - 'metrics' => 'ym:s:visits', -]; - -$visits = $YaMetrika->customQuery($data) - ->data; - -print_r( $visits ); \ No newline at end of file diff --git a/examples/getAgeGender.php b/examples/getAgeGender.php deleted file mode 100644 index 97a057b..0000000 --- a/examples/getAgeGender.php +++ /dev/null @@ -1,15 +0,0 @@ -getAgeGender() - ->format() - ->formatData; - -print_r( $AgeGender ); \ No newline at end of file diff --git a/examples/getBrowsers.php b/examples/getBrowsers.php deleted file mode 100644 index 6a6cd7b..0000000 --- a/examples/getBrowsers.php +++ /dev/null @@ -1,15 +0,0 @@ -getBrowsers(30) - ->format() - ->formatData; - -print_r( $browsers ); \ No newline at end of file diff --git a/examples/getGeo.php b/examples/getGeo.php deleted file mode 100644 index b890a01..0000000 --- a/examples/getGeo.php +++ /dev/null @@ -1,15 +0,0 @@ -getGeo(7) - ->format() - ->formatData; - -print_r( $geo ); \ No newline at end of file diff --git a/examples/getMostViewedPages.php b/examples/getMostViewedPages.php deleted file mode 100644 index a1a077f..0000000 --- a/examples/getMostViewedPages.php +++ /dev/null @@ -1,15 +0,0 @@ -getMostViewedPages(20) - ->format() - ->formatData; - -print_r( $pages ); \ No newline at end of file diff --git a/examples/getPreset.php b/examples/getPreset.php deleted file mode 100644 index bc9bba0..0000000 --- a/examples/getPreset.php +++ /dev/null @@ -1,15 +0,0 @@ -getPreset('traffic', 30) - ->format() - ->formatData; - -print_r( $traffic ); \ No newline at end of file diff --git a/examples/getUsersSearchEngine.php b/examples/getUsersSearchEngine.php deleted file mode 100644 index c96628d..0000000 --- a/examples/getUsersSearchEngine.php +++ /dev/null @@ -1,15 +0,0 @@ -getUsersSearchEngine(30) - ->format() - ->formatData; - -print_r( $SearchEngine ); \ No newline at end of file diff --git a/examples/getVisitors.php b/examples/getVisitors.php deleted file mode 100644 index c55892d..0000000 --- a/examples/getVisitors.php +++ /dev/null @@ -1,15 +0,0 @@ -getVisitors(30) - ->format() - ->formatData; - -print_r( $visitors ); \ No newline at end of file diff --git a/src/Client.php b/src/Client.php new file mode 100644 index 0000000..f462f7d --- /dev/null +++ b/src/Client.php @@ -0,0 +1,60 @@ + + * @link https://github.com/axp-dev/ya-metrika + * @package AXP\YaMetrika + */ +class Client +{ + private string $apiEndpoint = 'https://api-metrika.yandex.ru/stat/v1/data'; + + private HttpClient $httpClient; + + public function __construct( + private string $token, + private string $counterId, + private array $httpClientOptions = [] + ) + { + $this->httpClient = new HttpClient( + $this->buildConfig($this->httpClientOptions) + ); + } + + private function buildConfig(array $options): array + { + return array_merge($options, [ + RequestOptions::HEADERS => [ + 'Authorization' => "OAuth {$this->token}" + ] + ]); + } + + private function buildUri(array $params = []): string + { + $params['ids'] = $this->counterId; + + return $this->apiEndpoint . '?' . http_build_query(data: $params, arg_separator: '&'); + } + + public function request($params): array + { + try { + $response = $this->httpClient->request('GET', $this->buildUri($params)); + + return json_decode($response->getBody(), true); + } catch (GuzzleException $exception) { + throw new ClientException($exception->getMessage()); + } + } +} \ No newline at end of file diff --git a/src/Exception/ClientException.php b/src/Exception/ClientException.php new file mode 100644 index 0000000..e825b89 --- /dev/null +++ b/src/Exception/ClientException.php @@ -0,0 +1,14 @@ + + * @link https://github.com/axp-dev/ya-metrika + * @package AXP\YaMetrika\Exception + */ +class ClientException extends \Exception +{ +} \ No newline at end of file diff --git a/src/Exception/FormatException.php b/src/Exception/FormatException.php new file mode 100644 index 0000000..28adfb8 --- /dev/null +++ b/src/Exception/FormatException.php @@ -0,0 +1,14 @@ + + * @link https://github.com/axp-dev/ya-metrika + * @package AXP\YaMetrika\Exception + */ +class FormatException extends \Exception +{ +} \ No newline at end of file diff --git a/src/Exceptions/YaMetrikaException.php b/src/Exceptions/YaMetrikaException.php deleted file mode 100644 index a07a4a5..0000000 --- a/src/Exceptions/YaMetrikaException.php +++ /dev/null @@ -1,17 +0,0 @@ - - * @link https://github.com/axp-dev/ya-metrika - * @package AXP\YaMetrika\Exceptions - */ -class YaMetrikaException extends Exception -{ - -} \ No newline at end of file diff --git a/src/Response.php b/src/Response.php new file mode 100644 index 0000000..8eafe42 --- /dev/null +++ b/src/Response.php @@ -0,0 +1,68 @@ + + * @link https://github.com/axp-dev/ya-metrika + * @package AXP\YaMetrika + */ +class Response +{ + private array $combineKeys = [ + 'ym:s:', 'ym:pv:', 'ym:ad:', 'ym:sp:' + ]; + + private array $cachedFormat = []; + + public function __construct(private array $data) + { + } + + public function formatData(): array + { + if ($this->cachedFormat) { + return $this->cachedFormat; + } + + try { + $formatted = [ + 'data' => [], + 'totals' => $this->combineData('metrics', $this->data['totals']), + 'min' => $this->combineData('metrics', $this->data['min']), + 'max' => $this->combineData('metrics', $this->data['max']), + ]; + + foreach ($this->data['data'] as $key => $datum) { + $formatted['data'][$key] = [ + 'dimensions' => $this->combineData('dimensions', $datum['dimensions']), + 'metrics' => $this->combineData('metrics', $datum['metrics']), + ]; + } + + $this->cachedFormat = $formatted; + + return $formatted; + } catch (\Exception $exception) { + throw new FormatException($exception->getMessage()); + } + } + + public function rawData(): array + { + return $this->data; + } + + private function combineData(string $column, array $array): array + { + $queryColumn = array_map(function($key) { + return str_replace($this->combineKeys, '', $key); + }, $this->data['query'][$column]); + + return array_combine($queryColumn, $array); + } +} \ No newline at end of file diff --git a/src/YaMetrika.php b/src/YaMetrika.php index 99cff53..17f561b 100644 --- a/src/YaMetrika.php +++ b/src/YaMetrika.php @@ -2,12 +2,8 @@ namespace AXP\YaMetrika; -use AXP\YaMetrika\Exceptions\YaMetrikaException; -use Carbon\Carbon; use DateTime; -use GuzzleHttp\Client as GuzzleClient; -use GuzzleHttp\Exception\ClientException; -use GuzzleHttp\RequestOptions; +use DateInterval; /** * Class YaMetrika @@ -18,157 +14,37 @@ */ class YaMetrika { - /** - * URL API Yandex Metrika - * - * @var string - */ - private $endPoint = 'https://api-metrika.yandex.ru/stat/v1/data'; - - /** - * Token API - * - * @var string - */ - private $token; - - /** - * Id счётчика - * - * @var int - */ - private $counterId; - - /** - * Proxy - * - * @var string - */ - private $proxy; - - /** - * Данные из метрики - * - * @var array - */ - public $data; - - /** - * Форматированные данные - * - * @var array - */ - public $formatData; - - /** - * YaMetrika constructor - * - * @param string $token - * @param $counterId - * @param string $proxy [user:pass@]host:port - */ - function __construct($token, $counterId, $proxy = null) + public function __construct(private Client $client) { - $this->token = $token; - $this->counterId = $counterId; - $this->proxy = $proxy; } - /** - * Форматируем данные - * - * @return $this - */ - public function format() - { - if ( $data = $this->data ) { - $formatted = [ - 'data' => [], - 'totals' => $this->combineData('metrics', $data['totals']), - 'min' => $this->combineData('metrics', $data['min']), - 'max' => $this->combineData('metrics', $data['max']), - ]; - - foreach ($data['data'] as $key => $datum) { - $formatted['data'][$key] = [ - 'dimensions' => $this->combineData('dimensions', $datum['dimensions']), - 'metrics' => $this->combineData('metrics', $datum['metrics']), - ]; - } - - $this->formatData = $formatted; - } - - return $this; - } - - /** - * Получаем данные по шаблону за последние N дней - * - * @param string $template - * @param int $days - * @param int $limit - * - * @return $this - */ - public function getPreset($template, $days = 30, $limit = 10) + public function getPreset(string $preset, int $days = 30, int $limit = 10): Response { list($startDate, $endDate) = $this->differenceDate($days); - $this->getPresetForPeriod($template, $startDate, $endDate, $limit); - - return $this; + return $this->getPresetForPeriod($preset, $startDate, $endDate, $limit); } - /** - * Получаем данные по шаблону за выбранный период - * - * @param string $template - * @param DateTime $startDate - * @param DateTime $endDate - * @param int $limit - * - * @return $this - */ - public function getPresetForPeriod($template, DateTime $startDate, DateTime $endDate, $limit = 10) + public function getPresetForPeriod(string $preset, DateTime $startDate, DateTime $endDate, int $limit = 10): Response { $params = [ - 'preset' => $template, - 'date1' => $startDate->format('Y-m-d'), - 'date2' => $endDate->format('Y-m-d'), - 'limit' => $limit + 'preset' => $preset, + 'date1' => $startDate->format('Y-m-d'), + 'date2' => $endDate->format('Y-m-d'), + 'limit' => $limit ]; - $this->data = $this->query($params); - - return $this; + return new Response($this->client->request($params)); } - /** - * Получаем данные о посещаемости за последние N дней - * - * @param int $days - * - * @return $this - */ - public function getVisitors($days = 30) + public function getVisitors(int $days = 30): Response { list($startDate, $endDate) = $this->differenceDate($days); - $this->getVisitorsForPeriod($startDate, $endDate); - - return $this; + return $this->getVisitorsForPeriod($startDate, $endDate); } - /** - * Получаем данные о посещаемости за выбранный период - * - * @param DateTime $startDate - * @param DateTime $endDate - * - * @return $this - */ - public function getVisitorsForPeriod(DateTime $startDate, DateTime $endDate) + public function getVisitorsForPeriod(DateTime $startDate, DateTime $endDate): Response { $params = [ 'date1' => $startDate->format('Y-m-d'), @@ -178,38 +54,17 @@ public function getVisitorsForPeriod(DateTime $startDate, DateTime $endDate) 'sort' => 'ym:s:date', ]; - $this->data = $this->query($params); - - return $this; + return new Response($this->client->request($params)); } - /** - * Получаем самые популярные страницы за N дней - * - * @param int $days - * @param int $limit - * - * @return $this - */ - public function getMostViewedPages($days = 30, $limit = 10) + public function getMostViewedPages(int $days = 30, int $limit = 10): Response { list($startDate, $endDate) = $this->differenceDate($days); - $this->getMostViewedPagesForPeriod($startDate, $endDate, $limit); - - return $this; + return $this->getMostViewedPagesForPeriod($startDate, $endDate, $limit); } - /** - * Получаем самые популярные страницы за выбранный период - * - * @param DateTime $startDate - * @param DateTime $endDate - * @param int $limit - * - * @return $this - */ - public function getMostViewedPagesForPeriod(DateTime $startDate, DateTime $endDate, $limit = 10) + public function getMostViewedPagesForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 10): Response { $params = [ 'date1' => $startDate->format('Y-m-d'), @@ -220,38 +75,17 @@ public function getMostViewedPagesForPeriod(DateTime $startDate, DateTime $endDa 'limit' => $limit, ]; - $this->data = $this->query($params); - - return $this; + return new Response($this->client->request($params)); } - /** - * Получаем браузеры пользователей за N дней - * - * @param int $days - * @param int $limit - * - * @return $this - */ - public function getBrowsers($days = 30, $limit = 10) + public function getBrowsers(int $days = 30, int $limit = 10): Response { list($startDate, $endDate) = $this->differenceDate($days); - $this->getBrowsersForPeriod($startDate, $endDate, $limit); - - return $this; + return $this->getBrowsersForPeriod($startDate, $endDate, $limit); } - /** - * Получаем браузеры пользователей за выбранный период - * - * @param DateTime $startDate - * @param DateTime $endDate - * @param int $limit - * - * @return $this - */ - public function getBrowsersForPeriod(DateTime $startDate, DateTime $endDate, $limit = 10) + public function getBrowsersForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 10): Response { $params = [ 'date1' => $startDate->format('Y-m-d'), @@ -261,80 +95,38 @@ public function getBrowsersForPeriod(DateTime $startDate, DateTime $endDate, $li 'limit' => $limit, ]; - $this->data = $this->query($params); - - return $this; + return new Response($this->client->request($params)); } - /** - * Получаем посетителей с поисковых систем за N дней - * - * @param int $days - * @param int $limit - * - * @return $this - */ - public function getUsersSearchEngine($days = 30, $limit = 10) + public function getUsersSearchEngine(int $days = 30, int $limit = 10): Response { list($startDate, $endDate) = $this->differenceDate($days); - $this->getUsersSearchEngineForPeriod($startDate, $endDate, $limit); - - return $this; + return $this->getUsersSearchEngineForPeriod($startDate, $endDate, $limit); } - /** - * Получаем посетителей с поисковых систем за выбранный период - * - * @param DateTime $startDate - * @param DateTime $endDate - * @param int $limit - * - * @return $this - */ - public function getUsersSearchEngineForPeriod(DateTime $startDate, DateTime $endDate, $limit = 10) + public function getUsersSearchEngineForPeriod(DateTime $startDate, DateTime $endDate, $limit = 10): Response { $params = [ 'date1' => $startDate->format('Y-m-d'), 'date2' => $endDate->format('Y-m-d'), - 'metrics' => 'ym:s:users', + 'metrics' => 'ym:s:visits,ym:s:users', 'dimensions' => 'ym:s:searchEngine', 'filters' => "ym:s:trafficSource=='organic'", 'limit' => $limit, ]; - $this->data = $this->query($params); - - return $this; + return new Response($this->client->request($params)); } - /** - * Получаем посетителей по странам и регионам за N дней - * - * @param int $days - * @param int $limit - * - * @return $this - */ - public function getGeo($days = 7, $limit = 20) + public function getGeo(int $days = 7, int $limit = 20): Response { list($startDate, $endDate) = $this->differenceDate($days); - $this->getGeoForPeriod($startDate, $endDate, $limit); - - return $this; + return $this->getGeoForPeriod($startDate, $endDate, $limit); } - /** - * Получаем посетителей по странам и регионам за выбранный период - * - * @param DateTime $startDate - * @param DateTime $endDate - * @param int $limit - * - * @return $this - */ - public function getGeoForPeriod(DateTime $startDate, DateTime $endDate, $limit = 20) + public function getGeoForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 20): Response { $params = [ 'date1' => $startDate->format('Y-m-d'), @@ -345,38 +137,17 @@ public function getGeoForPeriod(DateTime $startDate, DateTime $endDate, $limit = 'limit' => $limit, ]; - $this->data = $this->query($params); - - return $this; + return new Response($this->client->request($params)); } - /** - * Получаем возраст и пол посетителей за N дней - * - * @param int $days - * @param int $limit - * - * @return $this - */ - public function getAgeGender($days = 30, $limit = 20) + public function getAgeGender($days = 30, int $limit = 20): Response { list($startDate, $endDate) = $this->differenceDate($days); - $this->getAgeGenderForPeriod($startDate, $endDate, $limit); - - return $this; + return $this->getAgeGenderForPeriod($startDate, $endDate, $limit); } - /** - * Получаем возраст и пол посетителей за выбранный период - * - * @param DateTime $startDate - * @param DateTime $endDate - * @param int $limit - * - * @return $this - */ - public function getAgeGenderForPeriod(DateTime $startDate, DateTime $endDate, $limit = 20) + public function getAgeGenderForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 20): Response { $params = [ 'date1' => $startDate->format('Y-m-d'), @@ -385,97 +156,48 @@ public function getAgeGenderForPeriod(DateTime $startDate, DateTime $endDate, $l 'limit' => $limit, ]; - $this->data = $this->query($params); - - return $this; + return new Response($this->client->request($params)); } - /** - * Отправляем кастомный запрос - * - * @param array $params - * - * @return $this - */ - public function customQuery($params) + public function getSearchPhrases($days = 30, int $limit = 20): Response { - $this->data = $this->query($params); + list($startDate, $endDate) = $this->differenceDate($days); - return $this; + return $this->getSearchPhrasesForPeriod($startDate, $endDate, $limit); } - /** - * Объединяем массивы для формирования ключей - * - * @param string $column - * @param array $array - * - * @return array - */ - private function combineData($column, $array) + public function getSearchPhrasesForPeriod(DateTime $startDate, DateTime $endDate, int $limit = 20): Response { - $queryColumn = array_map(function($key) { - return str_replace(['ym:s:', 'ym:pv:', 'ym:ad:', 'ym:sp:'], '', $key); - }, $this->data['query'][$column]); + $params = [ + 'date1' => $startDate->format('Y-m-d'), + 'date2' => $endDate->format('Y-m-d'), + 'preset' => 'sources_search_phrases', + 'limit' => $limit, + ]; - return array_combine($queryColumn, $array); + return new Response($this->client->request($params)); } - /** - * Отправляем запорос - * - * @param array $params - * - * @return array - * @throws YaMetrikaException - */ - private function query($params) + public function customQuery(array $params): Response { - $url = $this->endPoint . '?' . http_build_query(array_merge($params, ['ids' => $this->counterId]), null, '&'); - - try { - $client = new GuzzleClient($this->getHttpClientParams()); - $response = $client->request('GET', $url); - $result = json_decode($response->getBody(), true); - - return $result; - } catch (ClientException $e) { - throw new YaMetrikaException($e->getMessage()); - } + return new Response($this->client->request($params)); } - /** - * Вычислям конечную и начальную дату - * - * @param $amountOfDays - * - * @return array - */ - private function differenceDate($amountOfDays) + public function getClient(): Client { - $endDate = Carbon::today(); - $startDate = Carbon::today()->subDays($amountOfDays); - - return [$startDate, $endDate]; + return $this->client; } - /** - * Получаем массив параметров запроса для HTTP клиента - * - * @return array - */ - private function getHttpClientParams() + public function setClient(Client $client): void { - $params = [ - RequestOptions::HEADERS => [ - "Authorization" => "OAuth {$this->token}" - ] - ]; + $this->client = $client; + } - if ($this->proxy) { - $params[RequestOptions::PROXY] = $this->proxy; - } + private function differenceDate($amountOfDays = 30): array + { + $endDate = new DateTime(); + $startDate = (new DateTime())->sub(new DateInterval("P{$amountOfDays}D")); - return $params; + return [$startDate, $endDate]; } -} +} \ No newline at end of file