* koin service and cli stuff added

This commit is contained in:
Danyi Dávid 2017-09-05 23:04:28 +02:00
parent 946d00ff93
commit 8184c1e07d
15 changed files with 801 additions and 55 deletions

View File

@ -1,4 +1,27 @@
# Expressive Skeleton and Installer # SMS-storage backend for IFTTT
sent:
https://sms-store.yvan.hu/store/sent/:hashKey
```json
{
"contactName": "{{ContactName}}",
"contactNumber": "{{ToNumber}}",
"when": "{{OccurredAt}}",
"text": "{{Text}}"
}
```
received:
https://sms-store.yvan.hu/store/received/:hashKey
```json
{
"contactName": "{{ContactName}}",
"contactNumber": "{{FromNumber}}",
"when": "{{OccurredAt}}",
"text": "{{Text}}"
}
```
[![Build Status](https://secure.travis-ci.org/zendframework/zend-expressive-skeleton.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-expressive-skeleton) [![Build Status](https://secure.travis-ci.org/zendframework/zend-expressive-skeleton.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-expressive-skeleton)
[![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-expressive-skeleton/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-expressive-skeleton?branch=master) [![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-expressive-skeleton/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-expressive-skeleton?branch=master)

18
bin/cli Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/php
<?php
chdir(__DIR__ . '/..');
require __DIR__ . '/../vendor/autoload.php';
use Symfony\Component\Console\Application;
/** @var \Interop\Container\ContainerInterface $container */
$container = require __DIR__ . '/../config/container.php';
$application = new Application('Application console');
$commands = $container->get('config')['console']['commands'];
foreach ($commands as $command) {
$application->add($container->get($command));
}
$application->run();

View File

@ -12,12 +12,14 @@
"require": { "require": {
"php": "^7.1", "php": "^7.1",
"dasprid/container-interop-doctrine": "^1.0", "dasprid/container-interop-doctrine": "^1.0",
"guzzlehttp/guzzle": "^6.3",
"roave/security-advisories": "dev-master", "roave/security-advisories": "dev-master",
"zendframework/zend-component-installer": "^1.0", "zendframework/zend-component-installer": "^1.0",
"zendframework/zend-config-aggregator": "^1.0", "zendframework/zend-config-aggregator": "^1.0",
"zendframework/zend-expressive": "^2.0.2", "zendframework/zend-expressive": "^2.0.2",
"zendframework/zend-expressive-fastroute": "^2.0", "zendframework/zend-expressive-fastroute": "^2.0",
"zendframework/zend-expressive-helpers": "^4.0", "zendframework/zend-expressive-helpers": "^4.0",
"zendframework/zend-http": "^2.6",
"zendframework/zend-json": "^3.0", "zendframework/zend-json": "^3.0",
"zendframework/zend-servicemanager": "^3.3", "zendframework/zend-servicemanager": "^3.3",
"zendframework/zend-stdlib": "^3.1" "zendframework/zend-stdlib": "^3.1"

395
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "bfda08b2cb2ecc772eeba50ef50b13f5", "content-hash": "ec3f18dc9b7321742d6862e0193aa1a4",
"packages": [ "packages": [
{ {
"name": "container-interop/container-interop", "name": "container-interop/container-interop",
@ -732,6 +732,187 @@
], ],
"time": "2017-02-09T16:10:21+00:00" "time": "2017-02-09T16:10:21+00:00"
}, },
{
"name": "guzzlehttp/guzzle",
"version": "6.3.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699",
"reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.0 || ^5.0",
"psr/log": "^1.0"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.2-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2017-06-22T18:50:49+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
},
{ {
"name": "http-interop/http-middleware", "name": "http-interop/http-middleware",
"version": "0.4.1", "version": "0.4.1",
@ -1783,6 +1964,56 @@
], ],
"time": "2017-01-11T18:42:34+00:00" "time": "2017-01-11T18:42:34+00:00"
}, },
{
"name": "zendframework/zend-http",
"version": "2.6.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-http.git",
"reference": "09f4d279f46d86be63171ff62ee0f79eca878678"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-http/zipball/09f4d279f46d86be63171ff62ee0f79eca878678",
"reference": "09f4d279f46d86be63171ff62ee0f79eca878678",
"shasum": ""
},
"require": {
"php": "^5.5 || ^7.0",
"zendframework/zend-loader": "^2.5",
"zendframework/zend-stdlib": "^2.5 || ^3.0",
"zendframework/zend-uri": "^2.5",
"zendframework/zend-validator": "^2.5"
},
"require-dev": {
"phpunit/phpunit": "^4.0",
"zendframework/zend-coding-standard": "~1.0.0",
"zendframework/zend-config": "^2.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.6-dev",
"dev-develop": "2.7-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Http\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests",
"homepage": "https://github.com/zendframework/zend-http",
"keywords": [
"http",
"zf2"
],
"time": "2017-01-31T14:41:02+00:00"
},
{ {
"name": "zendframework/zend-json", "name": "zendframework/zend-json",
"version": "3.0.0", "version": "3.0.0",
@ -1833,6 +2064,50 @@
], ],
"time": "2016-04-01T02:34:00+00:00" "time": "2016-04-01T02:34:00+00:00"
}, },
{
"name": "zendframework/zend-loader",
"version": "2.5.1",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-loader.git",
"reference": "c5fd2f071bde071f4363def7dea8dec7393e135c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-loader/zipball/c5fd2f071bde071f4363def7dea8dec7393e135c",
"reference": "c5fd2f071bde071f4363def7dea8dec7393e135c",
"shasum": ""
},
"require": {
"php": ">=5.3.23"
},
"require-dev": {
"fabpot/php-cs-fixer": "1.7.*",
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5-dev",
"dev-develop": "2.6-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Loader\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"homepage": "https://github.com/zendframework/zend-loader",
"keywords": [
"loader",
"zf2"
],
"time": "2015-06-03T14:05:47+00:00"
},
{ {
"name": "zendframework/zend-servicemanager", "name": "zendframework/zend-servicemanager",
"version": "3.3.0", "version": "3.3.0",
@ -1994,6 +2269,124 @@
"psr-7" "psr-7"
], ],
"time": "2017-01-25T19:16:16+00:00" "time": "2017-01-25T19:16:16+00:00"
},
{
"name": "zendframework/zend-uri",
"version": "2.5.2",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-uri.git",
"reference": "0bf717a239432b1a1675ae314f7c4acd742749ed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-uri/zipball/0bf717a239432b1a1675ae314f7c4acd742749ed",
"reference": "0bf717a239432b1a1675ae314f7c4acd742749ed",
"shasum": ""
},
"require": {
"php": "^5.5 || ^7.0",
"zendframework/zend-escaper": "^2.5",
"zendframework/zend-validator": "^2.5"
},
"require-dev": {
"fabpot/php-cs-fixer": "1.7.*",
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5-dev",
"dev-develop": "2.6-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Uri\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "a component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)",
"homepage": "https://github.com/zendframework/zend-uri",
"keywords": [
"uri",
"zf2"
],
"time": "2016-02-17T22:38:51+00:00"
},
{
"name": "zendframework/zend-validator",
"version": "2.10.1",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-validator.git",
"reference": "010084ddbd33299bf51ea6f0e07f8f4e8bd832a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-validator/zipball/010084ddbd33299bf51ea6f0e07f8f4e8bd832a8",
"reference": "010084ddbd33299bf51ea6f0e07f8f4e8bd832a8",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.1",
"php": "^5.6 || ^7.0",
"zendframework/zend-stdlib": "^2.7.6 || ^3.1"
},
"require-dev": {
"phpunit/phpunit": "^6.0.8 || ^5.7.15",
"zendframework/zend-cache": "^2.6.1",
"zendframework/zend-coding-standard": "~1.0.0",
"zendframework/zend-config": "^2.6",
"zendframework/zend-db": "^2.7",
"zendframework/zend-filter": "^2.6",
"zendframework/zend-http": "^2.5.4",
"zendframework/zend-i18n": "^2.6",
"zendframework/zend-math": "^2.6",
"zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
"zendframework/zend-session": "^2.8",
"zendframework/zend-uri": "^2.5"
},
"suggest": {
"zendframework/zend-db": "Zend\\Db component, required by the (No)RecordExists validator",
"zendframework/zend-filter": "Zend\\Filter component, required by the Digits validator",
"zendframework/zend-i18n": "Zend\\I18n component to allow translation of validation error messages",
"zendframework/zend-i18n-resources": "Translations of validator messages",
"zendframework/zend-math": "Zend\\Math component, required by the Csrf validator",
"zendframework/zend-servicemanager": "Zend\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
"zendframework/zend-session": "Zend\\Session component, ^2.8; required by the Csrf validator",
"zendframework/zend-uri": "Zend\\Uri component, required by the Uri and Sitemap\\Loc validators"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.10-dev",
"dev-develop": "2.11-dev"
},
"zf": {
"component": "Zend\\Validator",
"config-provider": "Zend\\Validator\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Zend\\Validator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "provides a set of commonly needed validators",
"homepage": "https://github.com/zendframework/zend-validator",
"keywords": [
"validator",
"zf2"
],
"time": "2017-08-22T14:19:23+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [

View File

@ -0,0 +1,15 @@
<?php
return [
'dependencies' => [
'invokables' => [],
'factories' => [
App\Command\KoinImportCommand::class => App\Command\KoinImportCommandFactory::class,
],
],
'console' => [
'commands' => [
App\Command\KoinImportCommand::class,
],
],
];

View File

@ -8,4 +8,6 @@
*/ */
return [ return [
'koin.user' => '',
'koin.pass' => '',
]; ];

View File

@ -11,6 +11,7 @@ $cacheConfig = [
]; ];
$aggregator = new ConfigAggregator([ $aggregator = new ConfigAggregator([
\Zend\Validator\ConfigProvider::class,
// Include cache configuration // Include cache configuration
new ArrayProvider($cacheConfig), new ArrayProvider($cacheConfig),

View File

@ -2,62 +2,23 @@
namespace App\Action; namespace App\Action;
use App\Service\KoinService;
use Interop\Http\ServerMiddleware\DelegateInterface; use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface; use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response\HtmlResponse; use Zend\Diactoros\Response\TextResponse;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Expressive\Router;
use Zend\Expressive\Template;
use Zend\Expressive\Plates\PlatesRenderer;
use Zend\Expressive\Twig\TwigRenderer;
use Zend\Expressive\ZendView\ZendViewRenderer;
class HomePageAction implements ServerMiddlewareInterface class HomePageAction implements ServerMiddlewareInterface
{ {
private $router; private $tmp;
private $template; public function __construct(KoinService $tmp)
public function __construct(Router\RouterInterface $router, Template\TemplateRendererInterface $template = null)
{ {
$this->router = $router; $this->tmp = $tmp;
$this->template = $template;
} }
public function process(ServerRequestInterface $request, DelegateInterface $delegate) public function process(ServerRequestInterface $request, DelegateInterface $delegate)
{ {
if (! $this->template) { return new TextResponse("Nuff");
return new JsonResponse([
'welcome' => 'Congratulations! You have installed the zend-expressive skeleton application.',
'docsUrl' => 'https://docs.zendframework.com/zend-expressive/',
]);
}
$data = [];
if ($this->router instanceof Router\AuraRouter) {
$data['routerName'] = 'Aura.Router';
$data['routerDocs'] = 'http://auraphp.com/packages/2.x/Router.html';
} elseif ($this->router instanceof Router\FastRouteRouter) {
$data['routerName'] = 'FastRoute';
$data['routerDocs'] = 'https://github.com/nikic/FastRoute';
} elseif ($this->router instanceof Router\ZendRouter) {
$data['routerName'] = 'Zend Router';
$data['routerDocs'] = 'https://docs.zendframework.com/zend-router/';
}
if ($this->template instanceof PlatesRenderer) {
$data['templateName'] = 'Plates';
$data['templateDocs'] = 'http://platesphp.com/';
} elseif ($this->template instanceof TwigRenderer) {
$data['templateName'] = 'Twig';
$data['templateDocs'] = 'http://twig.sensiolabs.org/documentation';
} elseif ($this->template instanceof ZendViewRenderer) {
$data['templateName'] = 'Zend View';
$data['templateDocs'] = 'https://docs.zendframework.com/zend-view/';
}
return new HtmlResponse($this->template->render('app::home-page', $data));
} }
} }

View File

@ -2,19 +2,14 @@
namespace App\Action; namespace App\Action;
use App\Service\KoinService;
use Interop\Container\ContainerInterface; use Interop\Container\ContainerInterface;
use Zend\Expressive\Router\RouterInterface;
use Zend\Expressive\Template\TemplateRendererInterface;
class HomePageFactory class HomePageFactory
{ {
public function __invoke(ContainerInterface $container) public function __invoke(ContainerInterface $container)
{ {
$router = $container->get(RouterInterface::class); $tmp = $container->get(KoinService::class);
$template = $container->has(TemplateRendererInterface::class) return new HomePageAction($tmp);
? $container->get(TemplateRendererInterface::class)
: null;
return new HomePageAction($router, $template);
} }
} }

View File

@ -0,0 +1,54 @@
<?php
namespace App\Command;
use App\Entity\Sms;
use App\Service\KoinService;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class KoinImportCommand extends Command
{
/**
* @var KoinService
*/
private $koinService;
/**
* @var EntityManager
*/
private $em;
public function __construct(KoinService $koinService,
EntityManager $em)
{
$this->koinService = $koinService;
$this->em = $em;
parent::__construct();
}
protected function configure()
{
$this->setName('import:koin')
->setDescription('Sends sms to koin')
->addArgument(
'id',
InputArgument::REQUIRED,
'Db id of the SMS'
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$smsId = $input->getArgument('id');
/** @var Sms $sms */
$sms = $this->em->getRepository(Sms::class)->find($smsId);
$this->koinService->onReceiveSms($sms);
$output->writeln("OK");
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Command;
use App\Service\KoinService;
use Interop\Container\ContainerInterface;
class KoinImportCommandFactory
{
public function __invoke(ContainerInterface $container)
{
/** @var KoinService $koinService */
$koinService = $container->get(KoinService::class);
$em = $container->get('doctrine.entity_manager.orm_default');
return new KoinImportCommand($koinService, $em);
}
}

View File

@ -41,6 +41,7 @@ class ConfigProvider
Action\StoreAction::class => Action\StoreFactory::class, Action\StoreAction::class => Action\StoreFactory::class,
Service\SmsStoreService::class => Service\SmsStoreServiceFactory::class, Service\SmsStoreService::class => Service\SmsStoreServiceFactory::class,
Service\KoinService::class => Service\KoinServiceFactory::class,
], ],
]; ];
} }

View File

@ -0,0 +1,241 @@
<?php
namespace App\Service;
use App\Entity\Sms;
use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;
class KoinService
{
const BASE_URI = 'https://www.koin.hu';
const DEFAULT_EXPENSE = 'Egyéb kiadás';
/**
* 1 - date
* 2 - time
* 3 - amount contains dot as thousand separator
* 4 - currency
* 5 - pos info
*/
const OTP_SMS_PATTERN = '/([0-9]{6}) ([0-9]{1,2}:[0-9]{1,2}) K[áà]rty[áà]s v[áà]s[áà]rl[áà]s/z[áà]rol[áà]s: -([0-9.]+) ([A-Z]{2,3}); (.*?); K[áà]rtyasz[áà]m: ...[0-9]{4}; Egyenleg: \+[0-9.]+ HUF - OTPdirekt/msi';
/**
* @var array
*/
private $config;
/**
* @var Client
*/
private $httpClient;
/**
* @var string
*/
private $csrfParam;
/**
* @var string
*/
private $csrfToken;
/**
* @var array
*/
private $expenseCategories = [];
/**
* @var array
*/
private $incomeCategories = [];
public function __construct(Client $httpClient, array $config)
{
$this->config = $config;
$this->httpClient = $httpClient;
}
/**
* @param Sms $sms
*/
public function onReceiveSms(Sms $sms)
{
if (false !== preg_match(self::OTP_SMS_PATTERN, $sms->getText(), $otpMatches)) {
$datePart = implode("-", sscanf($otpMatches[1], '%2c%2c%2c'));
$this->saveTransaction(
intval(str_replace(".","", $otpMatches[3])),
$otpMatches[4],
"20${datePart} ${otpMatches['2']}",
$this->getExpenseCategory($otpMatches[5]),
$this->getExpenseTags($otpMatches[5])
);
}
}
/**
* @param string $posInfo
* @return string
*/
private function getExpenseCategory(string $posInfo): string
{
return self::DEFAULT_EXPENSE;
}
/**
* @param string $posInfo
* @return array
*/
private function getExpenseTags(string $posInfo): array
{
return [];
}
/**
* @param int $amount
* @param string $currency
* @param string $date
* @param string $category
* @param array $tags
* @return int
*/
public function saveTransaction(int $amount, string $currency = 'HUF', string $date, string $category, array $tags): int
{
$pageData = $this->login($this->config['koin.user'], $this->config['koin.pass']);
$this->loadFormData($pageData->getBody());
return $this->postData(
$amount,
$currency,
$date,
$this->getCategoryId($category),
$this->getTagsString($tags)
);
}
/**
* @param string $user
* @param string $pass
* @return \Psr\Http\Message\ResponseInterface
*/
private function login(string $user, string $pass): ResponseInterface
{
$httpResponse = $this->httpClient->get(self::BASE_URI);
$body = $httpResponse->getBody();
$this->getCsrfToken($body);
$httpResponse = $this->httpClient
->post(self::BASE_URI . "/site/login", [
'form_params' => [
$this->csrfParam => $this->csrfToken,
'LoginForm[email]' => $user,
'LoginForm[pass]' => $pass,
'LoginForm[rememberMe]' => 0,
],
]);
return $httpResponse;
}
/**
* @param $htmlData
*/
private function loadFormData($htmlData)
{
$documentXpath = $this->getCsrfToken($htmlData);
/** @var \DOMNodeList $expenseOptionElements */
$expenseOptionElements = $documentXpath->query('//select[@id="transactioncreate-category_id"]/optgroup[@label="Kiadás"]/option');
/** @var \DOMNodeList $incomeOptionElements */
$incomeOptionElements = $documentXpath->query('//select[@id="transactioncreate-category_id"]/optgroup[@label="Bevétel"]/option');
/** @var \DOMElement $element */
foreach ($expenseOptionElements as $element) {
$this->expenseCategories[$element->nodeValue] = $element->getAttribute("value");
}
/** @var \DOMElement $element */
foreach ($incomeOptionElements as $element) {
$this->incomeCategories[$element->nodeValue] = $element->getAttribute("value");
}
}
/**
* Parse csrf from html
*
* @param $html
* @return \DOMXPath
*/
private function getCsrfToken($html): \DOMXPath
{
$xmlErrorHandling = libxml_use_internal_errors(TRUE);
$domDocument = new \DOMDocument();
$domDocument->loadHTML($html);
libxml_clear_errors();
libxml_use_internal_errors($xmlErrorHandling);
$documentXpath = new \DOMXPath($domDocument);
/** @var \DOMElement $paramElement */
$paramElement = $documentXpath->query('//meta[@name="csrf-param"]')->item(0);
/** @var \DOMElement $tokenElement */
$tokenElement = $documentXpath->query('//meta[@name="csrf-token"]')->item(0);
$this->csrfParam = $paramElement->getAttribute("content");
$this->csrfToken = $tokenElement->getAttribute("content");
return $documentXpath;
}
/**
* @param int $amount
* @param string $currency
* @param string $date
* @param string $category
* @param string $tags
* @return int
*/
private function postData(int $amount, string $currency = 'HUF', string $date, string $category, string $tags): int
{
$saveResponse = $this->httpClient
->post(self::BASE_URI . "/main/save-transaction", [
'form_params' => [
$this->csrfParam => $this->csrfToken,
'TransactionCreate[category_id]' => $category,
'TransactionCreate[value]' => $amount,
'TransactionCreate[currency]' => $currency,
'TransactionCreate[imgKey]' => "",
'TransactionCreate[tagData]' => $tags,
'TransactionCreate[date]' => $date,
],
]);
return $saveResponse->getStatusCode();
}
/**
* @param array $tags
* @return string
*/
private function getTagsString(array $tags): string
{
return implode(';', $tags);
}
/**
* @param string $category
* @return string
*/
private function getCategoryId(string $category): string
{
if(in_array($category, array_keys($this->expenseCategories))) {
return $this->expenseCategories[$category];
}
return $this->expenseCategories[self::DEFAULT_EXPENSE];
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Service;
use GuzzleHttp\Client;
use Interop\Container\ContainerInterface;
class KoinServiceFactory
{
public function __invoke(ContainerInterface $container)
{
$httpClient = new Client([
'cookies' => true,
]);
$config = $container->get('config');
return new KoinService($httpClient, $config);
}
}

View File

@ -13,6 +13,7 @@ class SmsStoreServiceFactory
public function __invoke(ContainerInterface $container) public function __invoke(ContainerInterface $container)
{ {
$em = $container->get('doctrine.entity_manager.orm_default'); $em = $container->get('doctrine.entity_manager.orm_default');
return new SmsStoreService($em); return new SmsStoreService($em);
} }
} }