laravel-nami-api/src/Api.php

441 lines
16 KiB
PHP
Raw Normal View History

2020-06-27 23:45:49 +02:00
<?php
namespace Zoomyboy\LaravelNami;
use App\Conf;
use App\Nami\Exceptions\TooManyLoginAttemptsException;
2021-11-19 22:58:42 +01:00
use Carbon\Carbon;
2022-02-18 17:56:04 +01:00
use Illuminate\Http\Client\PendingRequest;
2020-06-28 00:12:36 +02:00
use Illuminate\Support\Collection;
2021-07-17 16:57:59 +02:00
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
2021-11-17 23:40:47 +01:00
use Illuminate\Support\LazyCollection;
2021-07-17 16:57:59 +02:00
use Illuminate\Support\Str;
use Log;
2022-02-19 12:20:11 +01:00
use Zoomyboy\LaravelNami\Authentication\Authenticator;
2021-05-13 23:25:00 +02:00
use Zoomyboy\LaravelNami\Backend\Backend;
2021-05-14 20:10:22 +02:00
use Zoomyboy\LaravelNami\Concerns\IsNamiMember;
2022-02-19 13:37:53 +01:00
use Zoomyboy\LaravelNami\Exceptions\NotAuthenticatedException;
2021-08-22 19:32:45 +02:00
use Zoomyboy\LaravelNami\Exceptions\RightException;
2021-07-17 16:57:59 +02:00
use Zoomyboy\LaravelNami\NamiException;
2020-06-27 23:45:49 +02:00
2021-05-13 23:25:00 +02:00
class Api {
2020-06-27 23:45:49 +02:00
2022-02-18 17:56:04 +01:00
public string $url = 'https://nami.dpsg.de';
2022-02-19 12:20:11 +01:00
private Authenticator $authenticator;
2020-06-27 23:45:49 +02:00
2022-02-19 12:20:11 +01:00
public function __construct(Authenticator $authenticator)
2022-02-18 17:56:04 +01:00
{
2022-02-19 12:20:11 +01:00
$this->authenticator = $authenticator;
2020-06-27 23:45:49 +02:00
}
2022-02-18 17:56:04 +01:00
public function http(): PendingRequest {
2022-02-19 12:20:11 +01:00
return $this->authenticator->http();
2020-06-27 23:45:49 +02:00
}
2021-11-17 22:33:25 +01:00
public function findNr(int $nr): Member
{
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2021-11-17 22:33:25 +01:00
return $this->find(['mitgliedsNummber' => $nr]);
2021-06-19 00:44:56 +02:00
}
2021-11-17 22:33:25 +01:00
/**
* @param array<string, mixed> $payload
*/
public function find(array $payload): ?Member
{
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2021-11-17 22:33:25 +01:00
return $this->search($payload)->first();
}
2021-06-19 00:44:56 +02:00
2021-11-17 22:33:25 +01:00
/**
* @param array<string, mixed> $payload
2021-11-17 23:40:47 +01:00
* @return LazyCollection<int, Member>
2021-11-17 22:33:25 +01:00
*/
2021-11-17 23:40:47 +01:00
public function search(array $payload): LazyCollection
2021-11-17 22:33:25 +01:00
{
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2021-11-17 23:40:47 +01:00
return LazyCollection::make(function() use ($payload) {
$page = 1;
while (!isset ($totalEntries) || ($page-1) * 100 + 1 <= $totalEntries) {
$start = ($page-1) * 100;
2022-02-18 17:56:04 +01:00
$url = $this->url.'/ica/rest/nami/search-multi/result-list?searchedValues='.rawurlencode(json_encode((object) $payload) ?: '{}').'&page='.$page.'&start='.$start.'&limit=100';
2021-11-17 23:40:47 +01:00
$response = $this->http()->get($url);
$totalEntries = $response->json()['totalEntries'];
if ($response->json()['success'] !== true) {
$this->exception('Search failed', ['url' => $url], $response->json());
}
foreach ($response->json()['data'] as $member) {
yield Member::fromNami(collect($member)->mapWithKeys(function($value, $key) {
return [ str_replace('entries_', '', (string) $key) => $value ];
}));
}
$page++;
}
2021-11-17 22:33:25 +01:00
});
2021-06-19 00:44:56 +02:00
}
2021-06-24 00:12:24 +02:00
public function deleteMember($id) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/mglschaft-beenden';
2021-06-24 00:12:24 +02:00
$payload = [
'id' => $id,
'isConfirmed' => 'true',
'beendenZumDatum' => now()->subDays(1)->format('Y-m-d').' 00:00:00',
];
$response = $this->http()->asForm()->post($url, $payload);
if ($response['success'] !== true) {
$this->exception('Deleting member failed', ['url' => $url, 'post' => $payload], $response->json());
}
}
2022-02-18 18:29:02 +01:00
public function login(int $mglnr, string $password): self
{
2022-02-19 12:20:11 +01:00
$this->authenticator->login($mglnr, $password);
2020-06-27 23:45:49 +02:00
return $this;
}
2022-02-19 13:37:53 +01:00
public function isLoggedIn(): bool
{
return $this->authenticator->isLoggedIn();
}
2020-06-29 00:30:57 +02:00
public function membersOf($groupId): Collection {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist')->json()['data']);
2020-06-29 00:30:57 +02:00
}
2021-05-14 20:10:22 +02:00
public function putMember(array $attributes) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2021-05-14 20:10:22 +02:00
$member = Member::fromAttributes($attributes);
2022-02-11 01:23:31 +01:00
$existing = $this->member($member->group_id, $member->id);
2021-06-23 01:57:19 +02:00
if (data_get($attributes, 'id')) {
$payload = array_merge($existing, $member->toNami());
2022-02-11 01:58:00 +01:00
$payload['kontoverbindung'] = json_encode(data_get($payload, 'kontoverbindung', []));
2022-02-11 01:23:31 +01:00
$response = $this->http()->put(
2022-02-18 17:56:04 +01:00
$this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id.'/'.$member->id,
$payload
2022-02-11 01:23:31 +01:00
);
2021-06-23 01:57:19 +02:00
if (data_get($response->json(), 'success') !== true) {
$this->exception('Update failed', $member->toNami(), $response->json());
}
} else {
2022-02-18 17:56:04 +01:00
$response = $this->http()->post($this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id, $member->toNami());
2021-06-23 01:57:19 +02:00
if (data_get($response->json(), 'success') !== true) {
$this->exception('Update failed', $member->toNami(), $response->json());
}
2021-06-13 16:22:01 +02:00
2021-06-23 01:57:19 +02:00
return ['id' => $response->json()['data']];
2021-06-13 16:22:01 +02:00
}
2021-06-21 23:50:28 +02:00
return $response->json()['data'];
2020-07-15 22:55:52 +02:00
}
2021-08-22 22:49:10 +02:00
public function putMembership(int $memberId, array $data): int
{
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2021-08-22 23:32:23 +02:00
if (data_get($data, 'id')) {
2022-02-18 17:56:04 +01:00
$url = $this->url."/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/{$memberId}/{$data['id']}";
2021-08-22 23:32:23 +02:00
$response = $this->http()->put($url, $data);
} else {
2022-02-18 17:56:04 +01:00
$url = $this->url."/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/{$memberId}";
2021-08-22 23:32:23 +02:00
$response = $this->http()->post($url, $data);
}
2021-08-22 22:49:10 +02:00
if (data_get($response->json(), 'success') !== true) {
$this->exception('Update failed', ['url' => $url, 'data' => $data], $response->json());
}
2021-08-22 23:32:23 +02:00
if (data_get($data, 'id')) {
return $response->json()['data']['id'];
} else {
return $response->json()['data'];
}
2021-08-22 22:49:10 +02:00
}
2020-07-04 20:47:30 +02:00
public function membershipsOf($memberId): Collection {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$url = $this->url.'/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/'.$memberId.'/flist';
$r = $this->http()->get($url);
2020-07-05 10:56:43 +02:00
Logger::http($url, $r, 'Memberships from '.$memberId, ['memberId' => $memberId]);
if (!isset($r->json()['data'])) {
return collect([]);
}
return collect($r->json()['data']);
2020-07-04 20:47:30 +02:00
}
2020-07-04 21:23:10 +02:00
public function subactivitiesOf($activityId) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url.'/ica/rest/nami/untergliederungauftaetigkeit/filtered/untergliederung/taetigkeit/'.$activityId)->json()['data'])->map(function($subactivity) {
2020-07-04 21:23:10 +02:00
return Subactivity::fromNami($subactivity);
});;
}
2020-07-04 20:47:30 +02:00
public function membership($memberId, $membershipId) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$url = $this->url.'/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/'.$memberId.'/'.$membershipId;
2020-07-04 20:47:30 +02:00
$response = $this->http()->get($url);
2020-07-05 10:56:43 +02:00
Logger::http($url, $response, 'Single Membership '.$membershipId.' from '.$memberId, ['memberId' => $memberId]);
2020-07-04 20:47:30 +02:00
2021-08-22 19:32:45 +02:00
if($response->json()['success'] === false && Str::startsWith($response['message'], 'Sicherheitsverletzung')) {
throw new RightException('');
}
2020-07-04 20:47:30 +02:00
return $response->json()['data'];
}
2021-11-18 01:54:41 +01:00
public function courses(): Collection
{
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$url = $this->url.'/ica/rest/module/baustein';
2021-11-18 01:54:41 +01:00
$response = $this->http()->get($url);
return collect($response->json()['data'])->map(function($course) {
return (object) ['name' => $course['descriptor'], 'id' => $course['id']];
});
}
public function coursesFor(int $memberId): Collection
{
2022-02-19 13:37:53 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$url = $this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/flist";
2021-11-18 01:54:41 +01:00
$response = $this->http()->get($url);
if (!$response->ok() || $response->json()['success'] === false) {
throw new RightException('Getting courses for member '.$memberId.' failed');
}
2021-11-18 02:16:12 +01:00
return collect($response->json()['data'])->map(function($course) use ($memberId) {
2022-02-18 17:56:04 +01:00
$single = $this->http()->get($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$course['id']}")['data'];
2021-11-18 02:16:12 +01:00
2021-11-18 02:01:42 +01:00
return (object) [
2021-11-18 02:16:12 +01:00
'id' => $single['id'],
'organizer' => $single['veranstalter'],
'course_id' => $single['bausteinId'],
'event_name' => $single['vstgName'],
'completed_at' => $single['vstgTag'],
2021-11-18 02:01:42 +01:00
];
2021-11-18 01:54:41 +01:00
});
}
2021-11-19 22:58:42 +01:00
/**
* @param int $memberId
* @param array<string, mixed> $payload
* @return int
*/
public function createCourse(int $memberId, array $payload): int
{
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$response = $this->http()->post($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}", [
2021-11-19 22:58:42 +01:00
'bausteinId' => $payload['course_id'],
'vstgName' => $payload['event_name'],
'vstgTag' => Carbon::parse($payload['completed_at'])->format('Y-m-d').'T00:00:00',
'veranstalter' => $payload['organizer'],
]);
if (data_get($response->json(), 'success') !== true) {
$this->exception('Course creation failed', $payload, $response->json());
}
return $response['data'];
}
2021-11-20 00:48:23 +01:00
/**
* @param int $memberId
* @param int $courseId
* @param array<string, mixed> $payload
* @return void
*/
public function updateCourse(int $memberId, int $courseId, array $payload): void
{
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$response = $this->http()->put($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}", [
2021-11-20 00:48:23 +01:00
'bausteinId' => $payload['course_id'],
'vstgName' => $payload['event_name'],
'vstgTag' => Carbon::parse($payload['completed_at'])->format('Y-m-d').'T00:00:00',
'veranstalter' => $payload['organizer'],
]);
if (data_get($response->json(), 'success') !== true) {
2021-11-20 01:08:56 +01:00
$this->exception('Course update failed', $payload, $response->json());
}
}
public function deleteCourse(int $memberId, int $courseId): void
{
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$response = $this->http()->delete($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}");
2021-11-20 01:08:56 +01:00
if ($response->json() !== null && data_get($response->json(), 'success') !== true) {
2021-11-20 01:08:56 +01:00
$this->exception('Course deletion failed', [], $response->json());
2021-11-20 00:48:23 +01:00
}
}
2020-06-29 00:30:57 +02:00
public function member($groupId, $memberId) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/'.$memberId;
$response = $this->http()->get($url);
2020-07-05 10:56:43 +02:00
Logger::http($url, $response, 'Show member '.$memberId, ['memberId' => $memberId]);
if($response->json()['success'] === false && Str::startsWith($response['message'], 'Access denied')) {
return $this->singleMemberFallback($groupId, $memberId);
}
if($response->json()['success'] === false && Str::startsWith($response['message'], 'Sicherheitsverletzung: Zugriff')) {
return $this->singleMemberFallback($groupId, $memberId);
}
if ($response->json()['success'] === true) {
return $response->json()['data'];
} else {
$e = new NamiException('Fetch von Mitglied fehlgeschlagen');
$e->setData([
'response' => $response->body(),
'url' => $url
]);
throw $e;
}
2020-06-29 00:30:57 +02:00
}
2020-06-28 00:12:36 +02:00
public function hasGroup($groupId): bool {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2020-06-28 00:12:36 +02:00
return $this->groups()->search(function($group) use ($groupId) {
return $group->id == $groupId;
}) !== false;
}
2020-06-27 23:45:49 +02:00
2020-06-29 00:30:57 +02:00
public function groups($parentGroupId = null): Collection {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url.'/ica/rest/nami/gruppierungen/filtered-for-navigation/gruppierung/node/'.($parentGroupId ?: 'root'))->json()['data'])->map(function($group) use ($parentGroupId) {
2020-07-04 17:50:55 +02:00
return Group::fromResponse($group, $parentGroupId);
2020-06-28 00:12:36 +02:00
});
2020-06-27 23:45:49 +02:00
}
public function group($groupId): Group {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2020-06-28 02:11:23 +02:00
return $this->groups()->first(function($group) use ($groupId) {
return $group->id == $groupId;
});
}
public function subgroupsOf($groupId) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2020-06-28 02:11:23 +02:00
return $this->groups($groupId);
}
2020-06-29 23:12:16 +02:00
public function genders(): Collection {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url."/ica/rest/baseadmin/geschlecht")['data'])->map(function($gender) {
2020-06-29 23:12:16 +02:00
return Gender::fromNami($gender);
2021-04-11 16:45:37 +02:00
})->filter(fn($gender) => !$gender->isNull);
2020-06-29 23:12:16 +02:00
}
2020-06-29 23:42:48 +02:00
public function nationalities(): Collection {
2022-02-19 17:08:43 +01:00
$this->assertLoggedIn();
2022-02-19 19:04:25 +01:00
$url = $this->url."/ica/rest/baseadmin/staatsangehoerigkeit";
$response = $this->http()->get($url);
if ($response->json()['success'] === true) {
return collect($response['data'])->map(function($nationality) {
return Nationality::fromNami($nationality);
});
} else {
$e = new NamiException('Fetch von Nationalität fehlgeschlagen');
$e->setData([
'response' => $response->body(),
'url' => $url
]);
throw $e;
}
2020-06-29 23:42:48 +02:00
}
2021-04-10 00:38:45 +02:00
public function countries() {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url."/ica/rest/baseadmin/land")['data'])->map(function($country) {
2021-04-10 00:38:45 +02:00
return Country::fromNami($country);
});
}
2021-04-10 00:48:04 +02:00
public function regions() {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url."/ica/rest/baseadmin/region")['data'])->map(function($region) {
2021-04-10 00:48:04 +02:00
return Region::fromNami($region);
});
}
2021-04-10 00:28:19 +02:00
public function feesOf($groupid) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url."/ica/rest/namiBeitrag/beitragsartmgl/gruppierung/{$groupid}")['data'])->map(function($fee) {
2021-04-10 00:28:19 +02:00
return Fee::fromNami($fee);
});
}
2020-06-30 00:01:17 +02:00
public function confessions(): Collection {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url."/ica/rest/baseadmin/konfession")['data'])->map(function($gender) {
2020-06-30 00:01:17 +02:00
return Confession::fromNami($gender);
});
}
2020-07-04 21:23:10 +02:00
public function activities($groupId) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
return collect($this->http()->get($this->url."/ica/rest/nami/taetigkeitaufgruppierung/filtered/gruppierung/gruppierung/".$groupId)['data'])->map(function($activity) {
2020-07-04 21:23:10 +02:00
return Activity::fromNami($activity);
});
}
2022-02-17 02:06:38 +01:00
public function memberOverviewOf(int $groupId): Collection
{
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist';
2020-08-15 02:03:11 +02:00
$response = $this->http()->get($url);
return collect($response['data'])->map(function($member) use ($groupId) {
$member = collect($member)->mapWithKeys(function($value, $key) {
return [ str_replace('entries_', '', $key) => $value ];
});
$member['gruppierungId'] = $groupId;
return $member;
});
}
private function singleMemberFallback($groupId, $memberId) {
2022-02-19 18:05:52 +01:00
$this->assertLoggedIn();
2022-02-18 17:56:04 +01:00
$url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist';
$response = $this->http()->get($url);
$member = collect($response['data'])->first(function($member) use ($memberId) {
return $member['id'] == $memberId;
});
$member = collect($member)->mapWithKeys(function($value, $key) {
return [ str_replace('entries_', '', $key) => $value ];
});
2020-07-04 13:07:58 +02:00
$member['gruppierungId'] = $groupId;
return $member->toArray();
}
2021-06-21 22:37:23 +02:00
private function exception($message, $request, $response) {
throw (new NamiException($message))->response($response)->request($request);
}
2022-02-19 13:37:53 +01:00
private function assertLoggedIn(): void
{
if (!$this->isLoggedIn()) {
throw new NotAuthenticatedException('You need to login first');
}
}
2020-06-27 23:45:49 +02:00
}
2021-05-13 23:02:05 +02:00