From 50b71930f15a5c2f7156ce49d061e4dc8fdb1d1a Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 27 Jan 2023 22:12:09 +0100 Subject: [PATCH] phpstan, phpcs, phpunit fixes --- .../Media/PdfDefaultTemplate/template.php | 60 +++--- Admin/Install/db.json | 83 ++++---- Controller/ApiController.php | 178 ++++++++++++++++-- Controller/BackendController.php | 18 +- Models/Account.php | 70 +++++++ Models/AccountCredentialMapper.php | 2 +- Models/AccountMapper.php | 18 +- Models/AccountPermissionMapper.php | 2 +- Models/AddressMapper.php | 2 +- Models/ApiKey.php | 8 +- Models/ApiKeyMapper.php | 31 +-- Models/AppMapper.php | 2 +- Models/Contact.php | 138 ++++++++++++++ Models/ContactMapper.php | 60 ++++++ Models/DataChange.php | 31 +++ Models/DataChangeMapper.php | 2 +- Models/GroupMapper.php | 4 +- Models/GroupPermissionMapper.php | 2 +- Models/LocalizationMapper.php | 4 +- Theme/Backend/Lang/api.de.lang.php | 16 ++ 20 files changed, 590 insertions(+), 141 deletions(-) create mode 100644 Models/Contact.php create mode 100644 Models/ContactMapper.php create mode 100644 Theme/Backend/Lang/api.de.lang.php diff --git a/Admin/Install/Media/PdfDefaultTemplate/template.php b/Admin/Install/Media/PdfDefaultTemplate/template.php index 2fc0ef7..74213ba 100644 --- a/Admin/Install/Media/PdfDefaultTemplate/template.php +++ b/Admin/Install/Media/PdfDefaultTemplate/template.php @@ -17,44 +17,44 @@ class DefaultPdf extends TCPDF //Page header public function Header() { - if ($this->header_xobjid === false) { - $this->header_xobjid = $this->startTemplate($this->w, 0); + if ($this->header_xobjid === false) { + $this->header_xobjid = $this->startTemplate($this->w, 0); - // Set Logo - $image_file = __DIR__ . '/../Web/Backend/img/logo.png'; - $this->Image($image_file, 15, 15, 15, 15, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); + // Set Logo + $image_file = __DIR__ . '/../Web/Backend/img/logo.png'; + $this->Image($image_file, 15, 15, 15, 15, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); - // Set Title - $this->SetFont('helvetica', 'B', 20); - $this->setX(15 + 15 + 3); - $this->Cell(0, 14, $this->header_title, 0, false, 'L', 0, '', 0, false, 'T', 'M'); + // Set Title + $this->SetFont('helvetica', 'B', 20); + $this->setX(15 + 15 + 3); + $this->Cell(0, 14, $this->header_title, 0, false, 'L', 0, '', 0, false, 'T', 'M'); - $this->SetFont('helvetica', '', 10); - $this->setX(15 + 15 + 3); - $this->Cell(0, 26, $this->header_string, 0, false, 'L', 0, '', 0, false, 'T', 'M'); + $this->SetFont('helvetica', '', 10); + $this->setX(15 + 15 + 3); + $this->Cell(0, 26, $this->header_string, 0, false, 'L', 0, '', 0, false, 'T', 'M'); - $this->endTemplate(); - } + $this->endTemplate(); + } - $x = 0; - $dx = 0; + $x = 0; + $dx = 0; - if (!$this->header_xobj_autoreset AND $this->booklet AND (($this->page % 2) == 0)) { - // adjust margins for booklet mode - $dx = ($this->original_lMargin - $this->original_rMargin); - } + if (!$this->header_xobj_autoreset AND $this->booklet AND (($this->page % 2) == 0)) { + // adjust margins for booklet mode + $dx = ($this->original_lMargin - $this->original_rMargin); + } - if ($this->rtl) { - $x = $this->w + $dx; - } else { - $x = 0 + $dx; - } + if ($this->rtl) { + $x = $this->w + $dx; + } else { + $x = 0 + $dx; + } - $this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false); - if ($this->header_xobj_autoreset) { - // reset header xobject template at each page - $this->header_xobjid = false; - } + $this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false); + if ($this->header_xobj_autoreset) { + // reset header xobject template at each page + $this->header_xobjid = false; + } } // Page footer diff --git a/Admin/Install/db.json b/Admin/Install/db.json index 986774d..71c1118 100755 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -735,11 +735,6 @@ "primary": true, "autoincrement": true }, - "account_id_temp": { - "name": "account_id_temp", - "type": "VARCHAR(65)", - "null": false - }, "account_status": { "name": "account_status", "type": "TINYINT", @@ -807,14 +802,6 @@ "gdpr": true } }, - "account_email_temp": { - "name": "account_email_temp", - "type": "VARCHAR(70)", - "null": false, - "annotations": { - "gdpr": true - } - }, "account_tries": { "name": "account_tries", "type": "TINYINT", @@ -842,40 +829,6 @@ } } }, - "account_address_rel": { - "name": "account_address_rel", - "fields": { - "account_address_rel_id": { - "name": "account_address_rel_id", - "type": "INT", - "null": false, - "primary": true, - "autoincrement": true - }, - "account_address_rel_contact": { - "name": "account_address_rel_contact", - "type": "INT", - "null": false, - "foreignTable": "profile_contact", - "foreignKey": "profile_contact_id" - }, - "account_address_rel_module": { - "name": "account_address_rel_module", - "type": "INT", - "null": true, - "default": null, - "foreignTable": "module", - "foreignKey": "module_id" - }, - "account_address_rel_address": { - "name": "account_address_rel_address", - "type": "INT", - "null": false, - "foreignTable": "address", - "foreignKey": "address_id" - } - } - }, "account_contact": { "name": "account_contact", "fields": { @@ -908,7 +861,7 @@ }, "account_contact_module": { "name": "account_contact_module", - "type": "INT", + "type": "VARCHAR(190)", "null": true, "default": null, "foreignTable": "module", @@ -923,6 +876,40 @@ } } }, + "account_address_rel": { + "name": "account_address_rel", + "fields": { + "account_address_rel_id": { + "name": "account_address_rel_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "account_address_account": { + "name": "account_address_account", + "type": "INT", + "null": false, + "foreignTable": "account", + "foreignKey": "account_id" + }, + "account_address_rel_module": { + "name": "account_address_rel_module", + "type": "VARCHAR(190)", + "null": true, + "default": null, + "foreignTable": "module", + "foreignKey": "module_id" + }, + "account_address_rel_address": { + "name": "account_address_rel_address", + "type": "INT", + "null": false, + "foreignTable": "address", + "foreignKey": "address_id" + } + } + }, "account_account_rel": { "description": "Accounts can belong to other accounts. E.g. a user can belong to a company account", "name": "account_account_rel", diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 40537dd..e6da844 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -23,6 +23,9 @@ use Modules\Admin\Models\AccountPermission; use Modules\Admin\Models\AccountPermissionMapper; use Modules\Admin\Models\App; use Modules\Admin\Models\AppMapper; +use Modules\Admin\Models\ContactMapper; +use Modules\Admin\Models\DataChange; +use Modules\Admin\Models\DataChangeMapper; use Modules\Admin\Models\Group; use Modules\Admin\Models\GroupMapper; use Modules\Admin\Models\GroupPermission; @@ -32,17 +35,12 @@ use Modules\Admin\Models\Module; use Modules\Admin\Models\ModuleMapper; use Modules\Admin\Models\ModuleStatusUpdateType; use Modules\Admin\Models\NullAccount; +use Modules\Admin\Models\NullDataChange; use Modules\Admin\Models\PermissionCategory; use Modules\Admin\Models\SettingsEnum; use Modules\Media\Models\Collection; use Modules\Media\Models\CollectionMapper; use Modules\Media\Models\UploadFile; -use Modules\Admin\Models\App; -use phpOMS\Application\ApplicationType; -use Modules\Admin\Models\AppMapper; -use Modules\Admin\Models\DataChange; -use Modules\Admin\Models\NullDataChange; -use Modules\Admin\Models\DataChangeMapper; use phpOMS\Account\AccountStatus; use phpOMS\Account\AccountType; use phpOMS\Account\GroupStatus; @@ -487,18 +485,19 @@ final class ApiController extends Controller $id = isset($data['id']) ? (int) $data['id'] : null; $name = $data['name'] ?? null; $content = $data['content'] ?? null; - $unit = $data['unit'] ?? null; + $unit = $data['unit'] ?? null; $app = $data['app'] ?? null; $module = $data['module'] ?? null; $group = isset($data['group']) ? (int) $data['group'] : null; $account = isset($data['account']) ? (int) $data['account'] : null; + /** @var \Model\Setting $old */ $old = $this->app->appSettings->get($id, $name, $unit, $app, $module, $group, $account); $new = clone $old; $new->name = $name ?? $new->name; $new->content = $content ?? $new->content; - $new->unit = $unit ?? $new->unit; + $new->unit = $unit ?? $new->unit; $new->app = $app ?? $new->app; $new->module = $module ?? $new->module; $new->group = $group ?? $new->group; @@ -506,10 +505,10 @@ final class ApiController extends Controller $this->app->appSettings->set([ [ - 'id' => $new->id, + 'id' => $new->getId(), 'name' => $new->name, 'content' => $new->content, - 'unit' => $new->unit, + 'unit' => $new->unit, 'app' => $new->app, 'module' => $new->module, 'group' => $new->group, @@ -556,12 +555,15 @@ final class ApiController extends Controller return; } + /** @var Account $account */ $account = AccountMapper::get() ->where('id', $requestAccount) ->execute(); // test old password is correct - if (AccountMapper::login($account->login, (string) $request->getData('oldpass')) !== $requestAccount) { + if ($account->login === null + || AccountMapper::login($account->login, (string) $request->getData('oldpass')) !== $requestAccount + ) { $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); $response->header->status = RequestStatusCode::R_403; @@ -577,6 +579,7 @@ final class ApiController extends Controller } // test password complexity + /** @var \Model\Setting $complexity */ $complexity = $this->app->appSettings->get(names: [SettingsEnum::PASSWORD_PATTERN], module: 'Admin'); if (\preg_match($complexity->content, (string) $request->getData('newpass')) !== 1) { $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); @@ -825,6 +828,16 @@ final class ApiController extends Controller $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Application', 'Application successfully created', $app); } + /** + * Create default settings for new app + * + * @param App $app Application to create new settings for + * @param RequestAbstract $request Request used to create the app + * + * @return void + * + * @since 1.0.0 + */ private function createDefaultAppSettings(App $app, RequestAbstract $request) : void { $settings = []; @@ -1281,21 +1294,24 @@ final class ApiController extends Controller $defaultGroupIds = []; if ($request->hasData('app')) { + /** @var \Model\Setting $defaultGroupSettings */ $defaultGroupSettings = $this->app->appSettings->get( names: SettingsEnum::APP_DEFAULT_GROUPS, app: (int) $request->getData('app'), module: 'Admin' ); + $defaultGroups = \array_merge($defaultGroups, \json_decode($defaultGroupSettings->content, true)); } - if ($request->hasData('unit')) { + /** @var \Model\Setting $defaultGroupSettings */ $defaultGroupSettings = $this->app->appSettings->get( names: SettingsEnum::UNIT_DEFAULT_GROUPS, unit: (int) $request->getData('unit'), module: 'Admin' ); + $defaultGroups = \array_merge($defaultGroups, \json_decode($defaultGroupSettings->content, true)); } @@ -1304,7 +1320,15 @@ final class ApiController extends Controller } if (!empty($defaultGroupIds)) { - $this->createModelRelation($account->getId(), $account->getId(), $defaultGroupIds, AccountMapper::class, 'groups', 'account', $request->getOrigin()); + $this->createModelRelation( + $account->getId(), + $account->getId(), + $defaultGroupIds, + AccountMapper::class, + 'groups', + 'account', + $request->getOrigin() + ); } $this->fillJsonResponse( @@ -1319,6 +1343,19 @@ final class ApiController extends Controller ); } + /** + * Api method to register an account + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ public function apiAccountRegister(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void { if (!empty($val = $this->validateRegistration($request))) { @@ -1328,6 +1365,7 @@ final class ApiController extends Controller return; } + /** @var \Model\Setting $allowed */ $allowed = $this->app->appSettings->get( names: [SettingsEnum::REGISTRATION_ALLOWED], app: (int) $request->getData('app'), @@ -1341,6 +1379,7 @@ final class ApiController extends Controller return; } + /** @var \Model\Setting $complexity */ $complexity = $this->app->appSettings->get(names: [SettingsEnum::PASSWORD_PATTERN], module: 'Admin'); if ($request->hasData('password') && \preg_match($complexity->content, (string) $request->getData('password')) !== 1 @@ -1363,6 +1402,7 @@ final class ApiController extends Controller // email already in use if (!($emailAccount instanceof NullAccount) + && $emailAccount->login !== null && AccountMapper::login($emailAccount->login, (string) $request->getData('password')) !== LoginReturnType::OK ) { $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Registration', 'Email already in use, use your login details to login or activate your account also for this service.', []); @@ -1384,6 +1424,7 @@ final class ApiController extends Controller return; } elseif ($account === null && !($loginAccount instanceof NullAccount) + && $loginAccount->login !== null && AccountMapper::login($loginAccount->login, (string) $request->getData('password')) !== LoginReturnType::OK ) { $account = $loginAccount; @@ -1392,18 +1433,22 @@ final class ApiController extends Controller $defaultGroups = []; $defaultGroupIds = []; + /** @var \Model\Setting $defaultGroupSettings */ $defaultGroupSettings = $this->app->appSettings->get( names: SettingsEnum::APP_DEFAULT_GROUPS, app: (int) $request->getData('app'), module: 'Admin' ); + $defaultGroups = \array_merge($defaultGroups, \json_decode($defaultGroupSettings->content, true)); + /** @var \Model\Setting $defaultGroupSettings */ $defaultGroupSettings = $this->app->appSettings->get( names: SettingsEnum::UNIT_DEFAULT_GROUPS, unit: (int) $request->getData('unit'), module: 'Admin' ); + $defaultGroups = \array_merge($defaultGroups, \json_decode($defaultGroupSettings->content, true)); foreach ($defaultGroups as $group) { @@ -1412,6 +1457,7 @@ final class ApiController extends Controller // Already registered if ($account !== null) { + /** @var Account $account */ $account = AccountMapper::get() ->with('groups') ->where('id', $account->getId()) @@ -1454,8 +1500,8 @@ final class ApiController extends Controller $account = $response->get($request->uri->__toString())['response']; // Create confirmation pending entry - $dataChange = new DataChange(); - $dataChange->type = 'account'; + $dataChange = new DataChange(); + $dataChange->type = 'account'; $dataChange->createdBy = $account->getId(); $dataChange->data = \json_encode([ @@ -1468,7 +1514,7 @@ final class ApiController extends Controller $this->createModel($account->getId(), $dataChange, DataChangeMapper::class, 'datachange', $request->getOrigin()); ++$tries; - } while($dataChange->getId() === 0 && $tries < 5); + } while ($dataChange->getId() === 0 && $tries < 5); } // Create confirmation email @@ -1501,7 +1547,20 @@ final class ApiController extends Controller return []; } - // @todo: maybe move to job/workflow??? This feels very much like a job/event especially if we make the 'type' an event-trigger + /** + * Api method to perform a pending model change + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * @todo: maybe move to job/workflow??? This feels very much like a job/event especially if we make the 'type' an event-trigger + * + * @since 1.0.0 + */ public function apiDataChange(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void { if (!empty($val = $this->validateDataChange($request))) { @@ -1521,6 +1580,7 @@ final class ApiController extends Controller switch ($dataChange->type) { case 'account': + /** @var Account $old */ $old = AccountMapper::get()->where('id', $dataChange->createdBy)->execute(); $new = clone $old; @@ -1614,13 +1674,13 @@ final class ApiController extends Controller */ private function createAccountFromRequest(RequestAbstract $request) : Account { - $account = new Account(); - $account->setStatus((int) ($request->getData('status') ?? AccountStatus::INACTIVE)); - $account->setType((int) ($request->getData('type') ?? AccountType::USER)); + $account = new Account(); $account->login = (string) ($request->getData('login') ?? ''); $account->name1 = (string) ($request->getData('name1') ?? ''); $account->name2 = (string) ($request->getData('name2') ?? ''); $account->name3 = (string) ($request->getData('name3') ?? ''); + $account->setStatus((int) ($request->getData('status') ?? AccountStatus::INACTIVE)); + $account->setType((int) ($request->getData('type') ?? AccountType::USER)); $account->setEmail((string) ($request->getData('email') ?? '')); $account->generatePassword((string) ($request->getData('password') ?? '')); @@ -2541,4 +2601,82 @@ final class ApiController extends Controller } } } + + /** + * Routing end-point for application behaviour. + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiContactCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + if (!empty($val = $this->validateContactCreate($request))) { + $response->set('contact_create', new FormValidation($val)); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $contact = $this->createContactFromRequest($request); + + $this->createModel($request->header->account, $contact, ContactMapper::class, 'account_contact', $request->getOrigin()); + + $this->createModelRelation( + $request->header->account, + (int) $request->getData('account'), + $contact->getId(), + AccountMapper::class, 'contacts', '', $request->getOrigin() + ); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Contact', 'Contact successfully created', $contact); + } + + /** + * Validate contact element create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + public function validateContactCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['account'] = empty($request->getData('account'))) + || ($val['type'] = !\is_numeric($request->getData('type'))) + || ($val['content'] = empty($request->getData('content'))) + ) { + return $val; + } + + return []; + } + + /** + * Method to create a account element from request. + * + * @param RequestAbstract $request Request + * + * @return ContactElement + * + * @since 1.0.0 + */ + public function createContactFromRequest(RequestAbstract $request) : ContactElement + { + /** @var ContactElement $element */ + $element = new ContactElement(); + $element->setType((int) ($request->getData('type') ?? 0)); + $element->setSubtype((int) ($request->getData('subtype') ?? 0)); + $element->content = (string) ($request->getData('content') ?? ''); + $element->account = (int) ($request->getData('account') ?? 0); + + return $element; + } } diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 42a8d03..fe6bfb8 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -155,11 +155,7 @@ final class BackendController extends Controller /** @var \Model\Setting[] $exportTemplates */ $exportTemplates = $this->app->appSettings->get( names: [ - SettingsEnum::DEFAULT_PDF_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_EXCEL_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_CSV_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_WORD_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_EMAIL_EXPORT_TEMPLATE, + SettingsEnum::DEFAULT_LIST_EXPORTS, ], module: 'Admin' ); @@ -335,11 +331,7 @@ final class BackendController extends Controller /** @var \Model\Setting[] $exportTemplates */ $exportTemplates = $this->app->appSettings->get( names: [ - SettingsEnum::DEFAULT_PDF_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_EXCEL_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_CSV_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_WORD_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_EMAIL_EXPORT_TEMPLATE, + SettingsEnum::DEFAULT_LIST_EXPORTS, ], module: 'Admin' ); @@ -472,11 +464,7 @@ final class BackendController extends Controller /** @var \Model\Setting[] $exportTemplates */ $exportTemplates = $this->app->appSettings->get( names: [ - SettingsEnum::DEFAULT_PDF_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_EXCEL_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_CSV_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_WORD_EXPORT_TEMPLATE, - SettingsEnum::DEFAULT_EMAIL_EXPORT_TEMPLATE, + SettingsEnum::DEFAULT_LIST_EXPORTS, ], module: 'Admin' ); diff --git a/Models/Account.php b/Models/Account.php index 6c32dfa..c954a98 100755 --- a/Models/Account.php +++ b/Models/Account.php @@ -14,6 +14,8 @@ declare(strict_types=1); namespace Modules\Admin\Models; +use phpOMS\Stdlib\Base\Location; + /** * Account class. * @@ -55,4 +57,72 @@ class Account extends \phpOMS\Account\Account * @since 1.0.0 */ public ?\DateTimeImmutable $tempPasswordLimit = null; + + /** + * Location data. + * + * @var Location[] + * @since 1.0.0 + */ + protected array $locations = []; + + /** + * Contact data. + * + * @var Contact[] + * @since 1.0.0 + */ + protected array $contacts = []; + + /** + * Get account locations. + * + * @return Location[] + * + * @since 1.0.0 + */ + public function getLocations() : array + { + return $this->locations; + } + + /** + * Add location. + * + * @param Location $location Location + * + * @return void + * + * @since 1.0.0 + */ + public function addLocation(Location $location) : void + { + $this->locations[] = $location; + } + + /** + * Get account contact element. + * + * @return Contact[] + * + * @since 1.0.0 + */ + public function getContacts() : array + { + return $this->contacts; + } + + /** + * Add contact element. + * + * @param Contact $contact Contact Element + * + * @return void + * + * @since 1.0.0 + */ + public function addContact(Contact $contact) : void + { + $this->contacts[] = $contact; + } } diff --git a/Models/AccountCredentialMapper.php b/Models/AccountCredentialMapper.php index 55cfdd0..167a8b8 100755 --- a/Models/AccountCredentialMapper.php +++ b/Models/AccountCredentialMapper.php @@ -51,7 +51,7 @@ final class AccountCredentialMapper extends AccountMapper /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = Account::class; diff --git a/Models/AccountMapper.php b/Models/AccountMapper.php index 832a90a..5e31e07 100755 --- a/Models/AccountMapper.php +++ b/Models/AccountMapper.php @@ -53,7 +53,7 @@ class AccountMapper extends DataMapperFactory /** * Has one relation. * - * @var array + * @var array * @since 1.0.0 */ public const OWNS_ONE = [ @@ -66,7 +66,7 @@ class AccountMapper extends DataMapperFactory /** * Has many relation. * - * @var array + * @var array * @since 1.0.0 */ public const HAS_MANY = [ @@ -82,12 +82,24 @@ class AccountMapper extends DataMapperFactory 'external' => 'account_account_rel_root', 'self' => 'account_account_rel_child', ], + 'locations' => [ + 'mapper' => AddressMapper::class, + 'table' => 'account_address_rel', + 'external' => 'account_address_rel_address', + 'self' => 'account_address_rel_account', + ], + 'contacts' => [ + 'mapper' => ContactMapper::class, + 'table' => 'account_contact', + 'self' => 'account_contact_account', + 'external' => null, + ], ]; /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = Account::class; diff --git a/Models/AccountPermissionMapper.php b/Models/AccountPermissionMapper.php index 4f082bc..1b3e70f 100755 --- a/Models/AccountPermissionMapper.php +++ b/Models/AccountPermissionMapper.php @@ -52,7 +52,7 @@ final class AccountPermissionMapper extends DataMapperFactory /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = AccountPermission::class; diff --git a/Models/AddressMapper.php b/Models/AddressMapper.php index 400a892..cd43c48 100755 --- a/Models/AddressMapper.php +++ b/Models/AddressMapper.php @@ -48,7 +48,7 @@ final class AddressMapper extends DataMapperFactory /** * Has one relation. * - * @var array + * @var array * @since 1.0.0 */ public const OWNS_ONE = [ diff --git a/Models/ApiKey.php b/Models/ApiKey.php index 289de91..69be94f 100644 --- a/Models/ApiKey.php +++ b/Models/ApiKey.php @@ -17,14 +17,14 @@ namespace Modules\Admin\Models; use phpOMS\Account\AccountStatus; /** - * Account class. + * Api key class. * * @package Modules\Admin\Models * @license OMS License 1.0 * @link https://jingga.app * @since 1.0.0 */ -class Account +class ApiKey { /** * Id. @@ -43,7 +43,7 @@ class Account public string $key = ''; /** - * Account status. + * Api key status. * * @var int * @since 1.0.0 @@ -73,7 +73,7 @@ class Account */ public function __construct() { - $this->key = \random_bytes(128); + $this->key = \random_bytes(128); $this->createdAt = new \DateTimeImmutable('now'); } } diff --git a/Models/ApiKeyMapper.php b/Models/ApiKeyMapper.php index da89ea4..cd78dd4 100644 --- a/Models/ApiKeyMapper.php +++ b/Models/ApiKeyMapper.php @@ -36,17 +36,17 @@ class ApiKeyMapper extends DataMapperFactory * @since 1.0.0 */ public const COLUMNS = [ - 'account_api_id' => ['name' => 'account_api_id', 'type' => 'int', 'internal' => 'id'], - 'account_api_key' => ['name' => 'account_api_key', 'type' => 'string', 'internal' => 'key'], - 'account_api_status' => ['name' => 'account_api_status', 'type' => 'int', 'internal' => 'status'], - 'account_api_account' => ['name' => 'account_api_account', 'type' => 'int', 'internal' => 'account'], - 'account_api_created_at' => ['name' => 'account_api_created_at', 'type' => 'DateTime', 'internal' => 'createdAt'], + 'account_api_id' => ['name' => 'account_api_id', 'type' => 'int', 'internal' => 'id'], + 'account_api_key' => ['name' => 'account_api_key', 'type' => 'string', 'internal' => 'key'], + 'account_api_status' => ['name' => 'account_api_status', 'type' => 'int', 'internal' => 'status'], + 'account_api_account' => ['name' => 'account_api_account', 'type' => 'int', 'internal' => 'account'], + 'account_api_created_at' => ['name' => 'account_api_created_at', 'type' => 'DateTime', 'internal' => 'createdAt'], ]; /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = ApiKey::class; @@ -75,6 +75,15 @@ class ApiKeyMapper extends DataMapperFactory */ public const CREATED_AT = 'account_api_created_at'; + /** + * Authenticates a user based on an api key + * + * @param string $api Api key + * + * @return int + * + * @since 1.0.0 + */ public static function authenticateApiKey(string $api) : int { if (empty($api)) { @@ -107,11 +116,11 @@ class ApiKeyMapper extends DataMapperFactory } $query->update('account') - ->set([ - 'account_lactive' => new \DateTime('now'), - ]) - ->where('account_id', '=', (int) $result['account_id']) - ->execute(); + ->set([ + 'account_lactive' => new \DateTime('now'), + ]) + ->where('account_id', '=', (int) $result['account_id']) + ->execute(); return (int) $result['account_id']; } catch (\Exception $e) { diff --git a/Models/AppMapper.php b/Models/AppMapper.php index 163bf7e..1ff12f0 100755 --- a/Models/AppMapper.php +++ b/Models/AppMapper.php @@ -43,7 +43,7 @@ final class AppMapper extends DataMapperFactory /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = App::class; diff --git a/Models/Contact.php b/Models/Contact.php new file mode 100644 index 0000000..4f8aa87 --- /dev/null +++ b/Models/Contact.php @@ -0,0 +1,138 @@ +id; + } + + /** + * Set type + * + * @param int $type Type + * + * @return void + * + * @since 1.0.0 + */ + public function setType(int $type) : void + { + $this->type = $type; + } + + /** + * Get type + * + * @return int + * + * @since 1.0.0 + */ + public function getType() : int + { + return $this->type; + } + + /** + * Set subtype + * + * @param int $subtype Subtype + * + * @return void + * + * @since 1.0.0 + */ + public function setSubtype(int $subtype) : void + { + $this->subtype = $subtype; + } + + /** + * Get subtype + * + * @return int + * + * @since 1.0.0 + */ + public function getSubtype() : int + { + return $this->subtype; + } +} diff --git a/Models/ContactMapper.php b/Models/ContactMapper.php new file mode 100644 index 0000000..de86139 --- /dev/null +++ b/Models/ContactMapper.php @@ -0,0 +1,60 @@ + + * @since 1.0.0 + */ + public const COLUMNS = [ + 'account_contact_id' => ['name' => 'account_contact_id', 'type' => 'int', 'internal' => 'id'], + 'account_contact_type' => ['name' => 'account_contact_type', 'type' => 'int', 'internal' => 'type'], + 'account_contact_subtype' => ['name' => 'account_contact_subtype', 'type' => 'int', 'internal' => 'subtype'], + 'account_contact_order' => ['name' => 'account_contact_order', 'type' => 'int', 'internal' => 'order'], + 'account_contact_content' => ['name' => 'account_contact_content', 'type' => 'string', 'internal' => 'content'], + 'account_contact_module' => ['name' => 'account_contact_module', 'type' => 'string', 'internal' => 'module'], + 'account_contact_account' => ['name' => 'account_contact_account', 'type' => 'int', 'internal' => 'account'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'account_contact'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD ='account_contact_id'; +} diff --git a/Models/DataChange.php b/Models/DataChange.php index 18b0700..c6a0fd1 100644 --- a/Models/DataChange.php +++ b/Models/DataChange.php @@ -40,12 +40,36 @@ class DataChange */ protected string $hash = ''; + /** + * Data for the change + * + * @var string + * @since 1.0.0 + */ public string $data = ''; + /** + * Change type + * + * @var string + * @since 1.0.0 + */ public string $type = ''; + /** + * Created by account + * + * @var int + * @since 1.0.0 + */ public int $createdBy = 0; + /** + * Created at + * + * @var \DateTimeImmutable + * @since 1.0.0 + */ public \DateTimeImmutable $createdAt; /** @@ -71,6 +95,13 @@ class DataChange return $this->id; } + /** + * Create hash for data change as identifier + * + * @return void + * + * @since 1.0.0 + */ public function reHash() : void { $this->hash = \random_bytes(64); diff --git a/Models/DataChangeMapper.php b/Models/DataChangeMapper.php index 8b27e80..2b5ea49 100644 --- a/Models/DataChangeMapper.php +++ b/Models/DataChangeMapper.php @@ -44,7 +44,7 @@ final class DataChangeMapper extends DataMapperFactory /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = DataChange::class; diff --git a/Models/GroupMapper.php b/Models/GroupMapper.php index 15b6ac1..a98dc7b 100755 --- a/Models/GroupMapper.php +++ b/Models/GroupMapper.php @@ -45,7 +45,7 @@ final class GroupMapper extends DataMapperFactory /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = Group::class; @@ -77,7 +77,7 @@ final class GroupMapper extends DataMapperFactory /** * Has many relation. * - * @var array + * @var array * @since 1.0.0 */ public const HAS_MANY = [ diff --git a/Models/GroupPermissionMapper.php b/Models/GroupPermissionMapper.php index c5c7dc6..7a0f169 100755 --- a/Models/GroupPermissionMapper.php +++ b/Models/GroupPermissionMapper.php @@ -52,7 +52,7 @@ final class GroupPermissionMapper extends DataMapperFactory /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = GroupPermission::class; diff --git a/Models/LocalizationMapper.php b/Models/LocalizationMapper.php index 4a9763c..8f6647c 100755 --- a/Models/LocalizationMapper.php +++ b/Models/LocalizationMapper.php @@ -92,7 +92,7 @@ final class LocalizationMapper extends DataMapperFactory /** * Has one relation. * - * @var array + * @var array * @since 1.0.0 */ public const OWNS_ONE = [ @@ -135,7 +135,7 @@ final class LocalizationMapper extends DataMapperFactory /** * Model to use by the mapper. * - * @var string + * @var class-string * @since 1.0.0 */ public const MODEL = Localization::class; diff --git a/Theme/Backend/Lang/api.de.lang.php b/Theme/Backend/Lang/api.de.lang.php new file mode 100644 index 0000000..7a7245e --- /dev/null +++ b/Theme/Backend/Lang/api.de.lang.php @@ -0,0 +1,16 @@ + [ +]];