mirror of
https://github.com/Karaka-Management/oms-QA.git
synced 2026-02-05 10:58:40 +00:00
formatting fixes, bug fixes and support impl.
This commit is contained in:
parent
1ea3111fa2
commit
c9a2faa1de
406
Admin/Install/Application/QA/Application.php
Executable file
406
Admin/Install/Application/QA/Application.php
Executable file
|
|
@ -0,0 +1,406 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Web\{APPNAME};
|
||||
|
||||
use Model\CoreSettings;
|
||||
use Modules\Admin\Models\AccountMapper;
|
||||
use Modules\Admin\Models\LocalizationMapper;
|
||||
use Modules\Admin\Models\NullAccount;
|
||||
use phpOMS\Account\Account;
|
||||
use phpOMS\Account\AccountManager;
|
||||
use phpOMS\Asset\AssetType;
|
||||
use phpOMS\Auth\Auth;
|
||||
use phpOMS\DataStorage\Cache\CachePool;
|
||||
use phpOMS\DataStorage\Cookie\CookieJar;
|
||||
use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
|
||||
use phpOMS\DataStorage\Database\DatabasePool;
|
||||
use phpOMS\DataStorage\Database\DatabaseStatus;
|
||||
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
||||
use phpOMS\DataStorage\Session\HttpSession;
|
||||
use phpOMS\Dispatcher\Dispatcher;
|
||||
use phpOMS\Event\EventManager;
|
||||
use phpOMS\Localization\L11nManager;
|
||||
use phpOMS\Message\Http\HttpRequest;
|
||||
use phpOMS\Message\Http\HttpResponse;
|
||||
use phpOMS\Message\Http\RequestMethod;
|
||||
use phpOMS\Message\Http\RequestStatusCode;
|
||||
use phpOMS\Model\Html\Head;
|
||||
use phpOMS\Module\ModuleManager;
|
||||
use phpOMS\Router\RouteVerb;
|
||||
use phpOMS\Router\WebRouter;
|
||||
use phpOMS\System\File\PathException;
|
||||
use phpOMS\Uri\UriFactory;
|
||||
use phpOMS\Views\View;
|
||||
use Web\WebApplication;
|
||||
use Web\{APPNAME}\QAView;
|
||||
|
||||
/**
|
||||
* Application class.
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
final class Application
|
||||
{
|
||||
/**
|
||||
* WebApplication.
|
||||
*
|
||||
* @var WebApplication
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private WebApplication $app;
|
||||
|
||||
/**
|
||||
* Temp config.
|
||||
*
|
||||
* @var array{db:array{core:array{masters:array{select:array{db:string, host:string, port:int, login:string, password:string, database:string}}}}, log:array{file:array{path:string}}, app:array{path:string, default:array{id:string, app:string, org:int, lang:string}, domains:array}, page:array{root:string, https:bool}, language:string[]}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private array $config;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param WebApplication $app WebApplication
|
||||
* @param array{db:array{core:array{masters:array{select:array{db:string, host:string, port:int, login:string, password:string, database:string}}}}, log:array{file:array{path:string}}, app:array{path:string, default:array{id:string, app:string, org:int, lang:string}, domains:array}, page:array{root:string, https:bool}, language:string[]} $config Application config
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(WebApplication $app, array $config)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->app->appName = '{APPNAME}';
|
||||
$this->config = $config;
|
||||
UriFactory::setQuery('/app', \strtolower($this->app->appName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering app.
|
||||
*
|
||||
* @param HttpRequest $request Request
|
||||
* @param HttpResponse $response Response
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function run(HttpRequest $request, HttpResponse $response) : void
|
||||
{
|
||||
$this->app->l11nManager = new L11nManager($this->app->appName);
|
||||
$this->app->dbPool = new DatabasePool();
|
||||
$this->app->sessionManager = new HttpSession(36000);
|
||||
$this->app->cookieJar = new CookieJar();
|
||||
$this->app->moduleManager = new ModuleManager($this->app, __DIR__ . '/../../Modules');
|
||||
$this->app->dispatcher = new Dispatcher($this->app);
|
||||
|
||||
$this->app->dbPool->create('select', $this->config['db']['core']['masters']['select']);
|
||||
|
||||
$this->app->router = new WebRouter();
|
||||
$this->app->router->importFromFile(__DIR__ . '/Routes.php');
|
||||
$this->app->router->add(
|
||||
'/{APPNAME}/e403',
|
||||
function() use ($request, $response) {
|
||||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
$view->setTemplate('/Web/{APPNAME}/Error/403_inline');
|
||||
$response->header->status = RequestStatusCode::R_403;
|
||||
|
||||
|
||||
return $view;
|
||||
},
|
||||
RouteVerb::GET
|
||||
);
|
||||
|
||||
/* CSRF token OK? */
|
||||
if ($request->getData('CSRF') !== null
|
||||
&& !\hash_equals($this->app->sessionManager->get('CSRF'), $request->getData('CSRF'))
|
||||
) {
|
||||
$response->header->status = RequestStatusCode::R_403;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var ConnectionAbstract $con */
|
||||
$con = $this->app->dbPool->get();
|
||||
DataMapperAbstract::setConnection($con);
|
||||
|
||||
$this->app->cachePool = new CachePool();
|
||||
$this->app->appSettings = new CoreSettings($con);
|
||||
$this->app->eventManager = new EventManager($this->app->dispatcher);
|
||||
$this->app->accountManager = new AccountManager($this->app->sessionManager);
|
||||
$this->app->l11nServer = LocalizationMapper::get(1);
|
||||
$this->app->orgId = $this->getApplicationOrganization($request, $this->config['app']);
|
||||
|
||||
$aid = Auth::authenticate($this->app->sessionManager);
|
||||
$request->header->account = $aid;
|
||||
$response->header->account = $aid;
|
||||
|
||||
$account = $this->loadAccount($request);
|
||||
|
||||
if (!($account instanceof NullAccount)) {
|
||||
$response->header->l11n = $account->l11n;
|
||||
} elseif ($this->app->sessionManager->get('language') !== null) {
|
||||
$response->header->l11n
|
||||
->loadFromLanguage(
|
||||
$this->app->sessionManager->get('language'),
|
||||
$this->app->sessionManager->get('country') ?? '*'
|
||||
);
|
||||
} elseif ($this->app->cookieJar->get('language') !== null) {
|
||||
$response->header->l11n
|
||||
->loadFromLanguage(
|
||||
$this->app->cookieJar->get('language'),
|
||||
$this->app->cookieJar->get('country') ?? '*'
|
||||
);
|
||||
}
|
||||
|
||||
if (!\in_array($response->getLanguage(), $this->config['language'])) {
|
||||
$response->header->l11n->setLanguage($this->app->l11nServer->getLanguage());
|
||||
}
|
||||
|
||||
$pageView = new QAView($this->app->l11nManager, $request, $response);
|
||||
$head = new Head();
|
||||
|
||||
$pageView->setData('orgId', $this->app->orgId);
|
||||
$pageView->setData('head', $head);
|
||||
$response->set('Content', $pageView);
|
||||
|
||||
/* App only allows GET */
|
||||
if ($request->getMethod() !== RequestMethod::GET) {
|
||||
$this->create406Response($response, $pageView);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Database OK? */
|
||||
if ($this->app->dbPool->get()->getStatus() !== DatabaseStatus::OK) {
|
||||
$this->create503Response($response, $pageView);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UriFactory::setQuery('/lang', $response->getLanguage());
|
||||
|
||||
$this->loadLanguageFromPath(
|
||||
$response->getLanguage(),
|
||||
__DIR__ . '/lang/' . $response->getLanguage() . '.lang.php'
|
||||
);
|
||||
|
||||
$response->header->set('content-language', $response->getLanguage(), true);
|
||||
|
||||
/* Create html head */
|
||||
$this->initResponseHead($head, $request, $response);
|
||||
|
||||
$this->app->moduleManager->initRequestModules($request);
|
||||
$this->createDefaultPageView($request, $response, $pageView);
|
||||
|
||||
$dispatched = $this->app->dispatcher->dispatch(
|
||||
$this->app->router->route(
|
||||
$request->uri->getRoute(),
|
||||
$request->getData('CSRF'),
|
||||
$request->getRouteVerb(),
|
||||
$this->app->appName,
|
||||
$this->app->orgId,
|
||||
$account,
|
||||
$request->getData()
|
||||
),
|
||||
$request,
|
||||
$response
|
||||
);
|
||||
$pageView->addData('dispatch', $dispatched);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get application organization
|
||||
*
|
||||
* @param HttpRequest $request Client request
|
||||
* @param array $config App config
|
||||
*
|
||||
* @return int Organization id
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function getApplicationOrganization(HttpRequest $request, array $config) : int
|
||||
{
|
||||
return (int) (
|
||||
$request->getData('u') ?? (
|
||||
$config['domains'][$request->uri->host]['org'] ?? $config['default']['org']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create 406 response.
|
||||
*
|
||||
* @param HttpResponse $response Response
|
||||
* @param View $pageView View
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function create406Response(HttpResponse $response, View $pageView) : void
|
||||
{
|
||||
$response->header->status = RequestStatusCode::R_406;
|
||||
$pageView->setTemplate('/Web/{APPNAME}/Error/406');
|
||||
$this->loadLanguageFromPath(
|
||||
$response->getLanguage(),
|
||||
__DIR__ . '/Error/lang/' . $response->getLanguage() . '.lang.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create 406 response.
|
||||
*
|
||||
* @param HttpResponse $response Response
|
||||
* @param View $pageView View
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function create503Response(HttpResponse $response, View $pageView) : void
|
||||
{
|
||||
$response->header->status = RequestStatusCode::R_503;
|
||||
$pageView->setTemplate('/Web/{APPNAME}/Error/503');
|
||||
$this->loadLanguageFromPath(
|
||||
$response->getLanguage(),
|
||||
__DIR__ . '/Error/lang/' . $response->getLanguage() . '.lang.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load theme language from path
|
||||
*
|
||||
* @param string $language Language name
|
||||
* @param string $path Language path
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function loadLanguageFromPath(string $language, string $path) : void
|
||||
{
|
||||
/* Load theme language */
|
||||
if (($absPath = \realpath($path)) === false) {
|
||||
throw new PathException($path);
|
||||
}
|
||||
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
$themeLanguage = include $absPath;
|
||||
$this->app->l11nManager->loadLanguage($language, '0', $themeLanguage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load permission
|
||||
*
|
||||
* @param HttpRequest $request Current request
|
||||
*
|
||||
* @return Account
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function loadAccount(HttpRequest $request) : Account
|
||||
{
|
||||
$account = AccountMapper::getWithPermissions($request->header->account);
|
||||
$this->app->accountManager->add($account);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create 406 response.
|
||||
*
|
||||
* @param HttpResponse $response Response
|
||||
* @param View $pageView View
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function create403Response(HttpResponse $response, View $pageView) : void
|
||||
{
|
||||
$response->header->status = RequestStatusCode::R_403;
|
||||
$pageView->setTemplate('/Web/{APPNAME}/Error/403');
|
||||
$this->loadLanguageFromPath(
|
||||
$response->getLanguage(),
|
||||
__DIR__ . '/Error/lang/' . $response->getLanguage() . '.lang.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize response head
|
||||
*
|
||||
* @param Head $head Head to fill
|
||||
* @param HttpRequest $request Request
|
||||
* @param HttpResponse $response Response
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function initResponseHead(Head $head, HttpRequest $request, HttpResponse $response) : void
|
||||
{
|
||||
/* Load assets */
|
||||
$head->addAsset(AssetType::CSS, '../Resources/fontawesome/css/font-awesome.min.css');
|
||||
$head->addAsset(AssetType::CSS, '//fonts.googleapis.com/css?family=Roboto:100,300,300i,400,700,900');
|
||||
$head->addAsset(AssetType::CSS, '../Web/{APPNAME}/css/qa.css');
|
||||
|
||||
// Framework
|
||||
$head->addAsset(AssetType::JS, '../jsOMS/Utils/oLib.js');
|
||||
$head->addAsset(AssetType::JS, '../jsOMS/UnhandledException.js');
|
||||
$head->addAsset(AssetType::JS, '../Web/{APPNAME}/js/qa.js', ['type' => 'module']);
|
||||
$head->addAsset(AssetType::JSLATE, '../Modules/Navigation/Controller.js', ['type' => 'module']);
|
||||
|
||||
$script = '';
|
||||
$response->header->set(
|
||||
'content-security-policy',
|
||||
'base-uri \'self\'; script-src \'self\' blob: \'sha256-'
|
||||
. \base64_encode(\hash('sha256', $script, true))
|
||||
. '\'; worker-src \'self\'',
|
||||
true
|
||||
);
|
||||
|
||||
if ($request->hasData('debug')) {
|
||||
$head->addAsset(AssetType::CSS, 'cssOMS/debug.css');
|
||||
}
|
||||
|
||||
$css = \file_get_contents(__DIR__ . '/css/qa-small.css');
|
||||
if ($css === false) {
|
||||
$css = '';
|
||||
}
|
||||
|
||||
$css = \preg_replace('!\s+!', ' ', $css);
|
||||
$head->setStyle('core', $css ?? '');
|
||||
$head->title = 'Demo Shop';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default page view
|
||||
*
|
||||
* @param HttpRequest $request Request
|
||||
* @param HttpResponse $response Response
|
||||
* @param QAView $pageView View
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function createDefaultPageView(HttpRequest $request, HttpResponse $response, QAView $pageView) : void
|
||||
{
|
||||
$pageView->setTemplate('/Web/{APPNAME}/index');
|
||||
}
|
||||
}
|
||||
168
Admin/Install/Application/QA/Controller/AppController.php
Executable file
168
Admin/Install/Application/QA/Controller/AppController.php
Executable file
|
|
@ -0,0 +1,168 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Web\{APPNAME}\Controller;
|
||||
|
||||
use phpOMS\Contract\RenderableInterface;
|
||||
use phpOMS\Message\RequestAbstract;
|
||||
use phpOMS\Message\ResponseAbstract;
|
||||
use phpOMS\Module\ModuleAbstract;
|
||||
use phpOMS\Views\View;
|
||||
|
||||
/**
|
||||
* App controller class.
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class AppController extends ModuleAbstract
|
||||
{
|
||||
/**
|
||||
* Providing.
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $providing = [];
|
||||
|
||||
/**
|
||||
* Dependencies.
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $dependencies = [];
|
||||
|
||||
/**
|
||||
* Routing end-point for application behaviour.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $data Generic data
|
||||
*
|
||||
* @return RenderableInterface
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function viewList(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
|
||||
{
|
||||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
$view->setTemplate('/Web/{APPNAME}/tpl/list');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing end-point for application behaviour.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $data Generic data
|
||||
*
|
||||
* @return RenderableInterface
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function viewQuestion(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
|
||||
{
|
||||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
$view->setTemplate('/Web/{APPNAME}/tpl/question');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing end-point for application behaviour.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $data Generic data
|
||||
*
|
||||
* @return RenderableInterface
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function viewProfile(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
|
||||
{
|
||||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
$view->setTemplate('/Web/{APPNAME}/tpl/profile');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing end-point for application behaviour.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $data Generic data
|
||||
*
|
||||
* @return RenderableInterface
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function viewImprint(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
|
||||
{
|
||||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
$view->setTemplate('/Web/{APPNAME}/tpl/imprint');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing end-point for application behaviour.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $data Generic data
|
||||
*
|
||||
* @return RenderableInterface
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function viewTerms(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
|
||||
{
|
||||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
$view->setTemplate('/Web/{APPNAME}/tpl/terms');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing end-point for application behaviour.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $data Generic data
|
||||
*
|
||||
* @return RenderableInterface
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function viewDataPrivacy(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
|
||||
{
|
||||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
$view->setTemplate('/Web/{APPNAME}/tpl/privacy');
|
||||
|
||||
return $view;
|
||||
}
|
||||
}
|
||||
33
Admin/Install/Application/QA/QAView.php
Executable file
33
Admin/Install/Application/QA/QAView.php
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Web\{APPNAME};
|
||||
|
||||
use Modules\Organization\Models\Unit;
|
||||
use Modules\Profile\Models\Profile;
|
||||
use phpOMS\Uri\UriFactory;
|
||||
use phpOMS\Views\View;
|
||||
|
||||
/**
|
||||
* List view.
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class ShopView extends View
|
||||
{
|
||||
|
||||
}
|
||||
42
Admin/Install/Application/QA/Routes.php
Executable file
42
Admin/Install/Application/QA/Routes.php
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
use phpOMS\Router\RouteVerb;
|
||||
|
||||
return [
|
||||
'^(\/[a-zA-Z]*\/*|\/)$' => [
|
||||
[
|
||||
'dest' => '\Web\{APPNAME}\Controller\AppController:viewList',
|
||||
'verb' => RouteVerb::GET,
|
||||
],
|
||||
],
|
||||
'^(\/[a-zA-Z]*\/*|\/)/profile(\?.*|$)$' => [
|
||||
[
|
||||
'dest' => '\Web\{APPNAME}\Controller\AppController:viewProfile',
|
||||
'verb' => RouteVerb::GET,
|
||||
],
|
||||
],
|
||||
'^(\/[a-zA-Z]*\/*|\/)/imprint(\?.*|$)$' => [
|
||||
[
|
||||
'dest' => '\Web\{APPNAME}\Controller\AppController:viewImprint',
|
||||
'verb' => RouteVerb::GET,
|
||||
],
|
||||
],
|
||||
'^(\/[a-zA-Z]*\/*|\/)/terms(\?.*|$)$' => [
|
||||
[
|
||||
'dest' => '\Web\{APPNAME}\Controller\AppController:viewTerms',
|
||||
'verb' => RouteVerb::GET,
|
||||
],
|
||||
],
|
||||
'^(\/[a-zA-Z]*\/*|\/)/privacy(\?.*|$)$' => [
|
||||
[
|
||||
'dest' => '\Web\{APPNAME}\Controller\AppController:viewDataPrivacy',
|
||||
'verb' => RouteVerb::GET,
|
||||
],
|
||||
],
|
||||
'^(\/[a-zA-Z]*\/*|\/)/question(\?.*|$)$' => [
|
||||
[
|
||||
'dest' => '\Web\{APPNAME}\Controller\AppController:viewQuestion',
|
||||
'verb' => RouteVerb::GET,
|
||||
],
|
||||
],
|
||||
];
|
||||
137
Admin/Install/Application/QA/Themes/Default/css/qa-small.css
Executable file
137
Admin/Install/Application/QA/Themes/Default/css/qa-small.css
Executable file
|
|
@ -0,0 +1,137 @@
|
|||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #242424;
|
||||
}
|
||||
|
||||
header {
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 1rem;
|
||||
text-align: right;
|
||||
padding: 2rem 0 2rem 0;
|
||||
}
|
||||
|
||||
footer hr {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
header hr, footer hr {
|
||||
border: 0;
|
||||
border-bottom: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
header img {
|
||||
max-width: 300px;
|
||||
min-width: 100px;
|
||||
width: 25%;
|
||||
margin: 3rem 0 0 0;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 300;
|
||||
margin: 3rem 0 1rem 0;
|
||||
}
|
||||
|
||||
header h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 300;
|
||||
margin: 0rem 0 3rem 0;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
nav {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: #25acff;
|
||||
}
|
||||
|
||||
main {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
nav ul, footer ul {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav li, footer li {
|
||||
display: inline-block;
|
||||
padding: .5rem 1rem .5rem 1rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #25acff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.floater {
|
||||
width: 80%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.content ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.content li:before {
|
||||
content: "\2022";
|
||||
color: #25acff;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
width: 1rem;
|
||||
margin-left: -1rem;
|
||||
}
|
||||
|
||||
footer a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.content p, .content ul {
|
||||
line-height: 1.7rem;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: #fff;
|
||||
background: #25acff;
|
||||
border: 1px solid #0480ce;
|
||||
padding: 1rem;
|
||||
border-radius: 5px;
|
||||
margin: 1.5rem;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 1rem;
|
||||
background: #eee;
|
||||
display: block;
|
||||
border-left: 3px solid #25acff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
code pre {
|
||||
margin: 0;
|
||||
}
|
||||
134
Admin/Install/Application/QA/Themes/Default/css/qa.css
Executable file
134
Admin/Install/Application/QA/Themes/Default/css/qa.css
Executable file
|
|
@ -0,0 +1,134 @@
|
|||
#front-header {
|
||||
box-sizing: border-box;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.front-header-columns {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: 450px;
|
||||
}
|
||||
|
||||
.front-columns {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 250px;
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
.front-shop-portlet {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.left, .right {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.left {
|
||||
margin-right: .5rem;
|
||||
flex-grow: 3;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 2;
|
||||
}
|
||||
|
||||
.right > a+a {
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
#front-small {
|
||||
display: flex;
|
||||
height: 250px;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
#front-small .front-shop-portlet+.front-shop-portlet {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
#front-small-header {
|
||||
margin-top: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#front-small-header h1, #front-small-header h2 {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#front-small-header h1 {
|
||||
font-weight: 400;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
#front-small-header h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.front-shop-portlet {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.front-shop-portlet > div {
|
||||
margin-top: auto;
|
||||
text-align: center;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.front-shop-portlet h1, .front-shop-portlet h2 {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#list-content {
|
||||
display: flex;
|
||||
flex-direction: row
|
||||
}
|
||||
|
||||
#side {
|
||||
background: #ccc;
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
#list {
|
||||
flex: 3;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.list-shop-portlet {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #ccc;
|
||||
min-width: 150px;
|
||||
max-width: 250px;
|
||||
height: 200px;
|
||||
margin: .5rem 0 0 .5rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.list-shop-portlet > div {
|
||||
margin-top: auto;
|
||||
text-align: center;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.list-shop-portlet h1, .list-shop-portlet h2 {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
15
Admin/Install/Application/QA/Themes/Default/tpl/footer.tpl.php
Executable file
15
Admin/Install/Application/QA/Themes/Default/tpl/footer.tpl.php
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
use phpOMS\Uri\UriFactory;
|
||||
|
||||
?>
|
||||
<footer>
|
||||
<div class="floater">
|
||||
<hr>
|
||||
<ul>
|
||||
<li><a href="<?= UriFactory::build('{/app}/terms'); ?>">Terms</a>
|
||||
<li><a href="<?= UriFactory::build('{/app}/privacy'); ?>">Data Protection</a>
|
||||
<li><a href="<?= UriFactory::build('{/app}/imprint'); ?>">Imprint</a>
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
28
Admin/Install/Application/QA/Themes/Default/tpl/header.tpl.php
Executable file
28
Admin/Install/Application/QA/Themes/Default/tpl/header.tpl.php
Executable file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use phpOMS\Uri\UriFactory;
|
||||
|
||||
?>
|
||||
<header>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="<?= UriFactory::build('{/app}'); ?>">Website</a>
|
||||
<li><a href="<?= UriFactory::build('{/app}/components'); ?>">Profile</a>
|
||||
</ul>
|
||||
</nav>
|
||||
<div id="search">
|
||||
<input type="text">
|
||||
</div>
|
||||
</header>
|
||||
40
Admin/Install/Application/QA/Themes/Default/tpl/imprint.tpl.php
Executable file
40
Admin/Install/Application/QA/Themes/Default/tpl/imprint.tpl.php
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
?>
|
||||
|
||||
<div class="content">
|
||||
<div class="floater">
|
||||
<h1>Imprint</h1>
|
||||
<p>Orange-Management</p>
|
||||
|
||||
<h2>Vertreten durch</h2>
|
||||
<p>Dennis Eichhorn</p>
|
||||
|
||||
<h2>Kontakt</h2>
|
||||
<p>spl1nes.com@googlemail.com</p>
|
||||
|
||||
<h2>Registereintrag</h2>
|
||||
<p>Nicht vorhanden</p>
|
||||
|
||||
<h2>Umsatzsteuer-ID gemäß §27 a Umsatzsteuergesetz</h2>
|
||||
<p>Nicht vorhanden</p>
|
||||
|
||||
<h2>Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV</h2>
|
||||
<p>Orange-Management</p>
|
||||
<p>Dennis Eichhorn</p>
|
||||
|
||||
<h2>Datenschutzbeauftragter</h2>
|
||||
<p>spl1nes.com@googlemail.com<p>
|
||||
</div>
|
||||
</div>
|
||||
204
Admin/Install/Application/QA/Themes/Default/tpl/list.tpl.php
Executable file
204
Admin/Install/Application/QA/Themes/Default/tpl/list.tpl.php
Executable file
|
|
@ -0,0 +1,204 @@
|
|||
<div class="content">
|
||||
<div class="floater">
|
||||
<div id="list-content">
|
||||
<div id="side">a</div>
|
||||
<div id="list">
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="list-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
95
Admin/Install/Application/QA/Themes/Default/tpl/privacy.tpl.php
Executable file
95
Admin/Install/Application/QA/Themes/Default/tpl/privacy.tpl.php
Executable file
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
?>
|
||||
|
||||
<div class="content">
|
||||
<div class="floater">
|
||||
<h1>Privacy Policy</h1>
|
||||
<p>This privacy policy ("POLICY") will help you understand how [name] ("us", "we", "our") uses and protects the data you provide to us when you visit and use Orange-Management ("website", "service" and "application").</p>
|
||||
|
||||
<h2>Definitions</h2>
|
||||
<p>For the purposes of these POLICIES:<p>
|
||||
|
||||
<ul>
|
||||
<li>AFFILIATED means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.</li>
|
||||
<li>COUNTRY refers to Germany</li>
|
||||
<li>COMPANY (referred to as either "the Company", "We", "Us" or "Our" in this AGREEMENT) refers to Orange Management, Gartenstr. 26, 61206 Woellstadt.</li>
|
||||
<li>DEVICE means any device that can access the SERVICE such as a computer, a cellphone or a digital tablet.</li>
|
||||
<li>SERVICE refers to the Website</li>
|
||||
<li>POLICY or AGREEMENT mean these policies that form the entire agreement between You and the COMPANY regarding the use of the SERVICE.</li>
|
||||
<li>Third-party Social Media SERVICE means any services or content (including data, information, products or services) provided by a third-party that may be displayed, included or made available by the SERVICE.</li>
|
||||
<li>WEBSITE refers to orange-management.org (.net, .app, .service, .support, .email, .de, .solutions)</li>
|
||||
<li>APPLICATION refers to all downloadable or installable content which can therfore be used on an a given DEVICE.</li>
|
||||
<li>You means the individual accessing or using the SERVICE, or the company, or other legal entity on behalf of which such individual is accessing or using the SERVICE, as applicable.</li>
|
||||
</ul>
|
||||
|
||||
<h2>What User Data we Collect</h2>
|
||||
<p>When you visit the WEBSITE or APPLICATION, we may collect the following data:</p>
|
||||
|
||||
<ul>
|
||||
<li>Your IP address.</li>
|
||||
<li>Your contact information and email address.</li>
|
||||
<li>Data profile regarding your online behavior on our WEBSITE.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Why We Collect Your Data</h2>
|
||||
<p>We are collecting your data for several reasons:</p>
|
||||
|
||||
<ul>
|
||||
<li>To better understand your needs.</li>
|
||||
<li>To improve our SERVICES and products.</li>
|
||||
<li>To send you promotional emails containing the information we think you will find interesting.</li>
|
||||
<li>To contact you to fill out surveys and participate in other types of market research.</li>
|
||||
<li>To customize our WEBSITE according to your online behavior and personal preferences.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Safeguarding and Securing the Data</h2>
|
||||
<p>Orange-Management is committed to securing your data and keeping it confidential. Orange-Management has done all in its power to prevent data theft, unauthorized access, and disclosure by implementing the latest technologies and software, which help us safeguard all the information we collect online.</p>
|
||||
|
||||
<h2>Our Cookie Policy</h2>
|
||||
<p>Once you agree to allow our WEBSITE or APPLICATION to use cookies, you also agree to these POLICIES.</p>
|
||||
<p>Please note that cookies don't allow us to gain control of your computer in any way.</p>
|
||||
<p>If you want to disable cookies, you can do it by accessing the settings of your internet browser.</p>
|
||||
<p>Please note that some functionality cannot be made available to you if you don't accept cookies</p>
|
||||
|
||||
<h2>Links</h2>
|
||||
<p>Our SERVICE may contain links to third-party web sites or services that are not owned or controlled by the COMPANY.</p>
|
||||
<p>The COMPANY has no control over, and assumes no responsibility for, the content, privacy policies, or practices of any third party websites or services. You further acknowledge and agree that the COMPANY shall not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with the use of or reliance on any such content, goods or services available on or through any such websites or services.</p>
|
||||
<p>We strongly advise You to read the terms and conditions and privacy policies of any third-party web sites or services that You visit.</p>
|
||||
|
||||
<h2>Restricting the Collection of your Personal Data</h2>
|
||||
<p>At some point, you might wish to restrict the use and collection of your personal data. You can achieve this by doing the following:</p>
|
||||
|
||||
<ul>
|
||||
<li>Don't accept cookies from our WEBSITE and APPLICATION</li>
|
||||
<li>If you have already agreed to share your information with us, feel free to contact us via email and we will be more than happy to change this for you.</li>
|
||||
</ul>
|
||||
|
||||
<p>Orange-Management will not lease, sell or distribute your personal information to any third parties, unless we have your permission. We might do so if the law forces us. Your personal information will be used when we need to send you promotional materials if you agree to this privacy policy.</p>
|
||||
|
||||
<h2>Governing Law</h2>
|
||||
<p>The laws of the COUNTRY, excluding its conflicts of law rules, shall govern this POLICY and Your use of the SERVICE. Your use of the APPLICATION may also be subject to other local, state, national, or international laws.</p>
|
||||
<p>The ineffectiveness of one or more provisions of this agreement does not affect the validity of the others. Each party to these TERMS can in this case demand that a new valid provision be agreed which best achieves the economic purpose of the ineffective provision.</p>
|
||||
|
||||
<h2>Dispute Resolution</h2>
|
||||
<p>If You have any concern or dispute about the SERVICE, You agree to first try to resolve the dispute informally by contacting the COMPANY.</p>
|
||||
|
||||
<h2>Changes to these Policies</h2>
|
||||
<p>We reserve the right, at Our sole discretion, to modify or replace these POLICIES at any time. If a revision is material We will make reasonable efforts to provide at least 30 days' notice prior to any new terms taking effect. What constitutes a material change will be determined at Our sole discretion.</p>
|
||||
<p>By continuing to access or use Our SERVICE after those revisions become effective, You agree to be bound by the revised policies. If You do not agree to the new policies, in whole or in part, please stop using the WEBSITE and the SERVICE.</p>
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>For questions regarding these POLICIES please feel free to contact us at info@orange-management.email</p>
|
||||
</div>
|
||||
</div>
|
||||
104
Admin/Install/Application/QA/Themes/Default/tpl/profile.tpl.php
Executable file
104
Admin/Install/Application/QA/Themes/Default/tpl/profile.tpl.php
Executable file
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use phpOMS\Uri\UriFactory;
|
||||
|
||||
?>
|
||||
|
||||
<div class="content">
|
||||
<div class="floater">
|
||||
<div id="front-header">
|
||||
<div class="front-header-columns">
|
||||
<div class="left">
|
||||
<a class="front-shop-portlet" href="shop/list">
|
||||
</a>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a class="front-shop-portlet" href="shop/list">
|
||||
</a>
|
||||
|
||||
<a class="front-shop-portlet" href="shop/list">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="front-columns">
|
||||
<div class="left">
|
||||
<a class="front-shop-portlet" href="shop/list">
|
||||
</a>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a class="front-shop-portlet" href="shop/list">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="front-small-header">
|
||||
<h1>Arcticles for you</h1>
|
||||
<h2>Special offers you may be interested in</h2>
|
||||
</div>
|
||||
|
||||
<div id="front-small">
|
||||
<a class="front-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="front-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="front-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="front-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="front-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="front-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="front-shop-portlet" href="shop/item">
|
||||
<div>
|
||||
<h1>Item name</h1>
|
||||
<h2>Description</h2>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
0
Admin/Install/Application/QA/Themes/Default/tpl/question.tpl.php
Executable file
0
Admin/Install/Application/QA/Themes/Default/tpl/question.tpl.php
Executable file
113
Admin/Install/Application/QA/Themes/Default/tpl/terms.tpl.php
Executable file
113
Admin/Install/Application/QA/Themes/Default/tpl/terms.tpl.php
Executable file
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
?>
|
||||
|
||||
<div class="content">
|
||||
<div class="floater">
|
||||
<h1>Terms of Service</h1>
|
||||
|
||||
<h2>Definitions</h2>
|
||||
<p>For the purposes of these TERMS:<p>
|
||||
|
||||
<ul>
|
||||
<li>AFFILIATED means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.</li>
|
||||
<li>COUNTRY refers to Germany</li>
|
||||
<li>COMPANY (referred to as either "the Company", "We", "Us" or "Our" in this AGREEMENT) refers to Orange Management, Gartenstr. 26, 61206 Woellstadt.</li>
|
||||
<li>DEVICE means any device that can access the Service such as a computer, a cellphone or a digital tablet.</li>
|
||||
<li>SERVICE refers to the Website</li>
|
||||
<li>TERMS or AGREEMENT mean these terms that form the entire agreement between You and the COMPANY regarding the use of the SERVICE.</li>
|
||||
<li>Third-party Social Media Service means any services or content (including data, information, products or services) provided by a third-party that may be displayed, included or made available by the SERVICE.</li>
|
||||
<li>WEBSITE refers to orange-management.org (.net, .app, .service, .support, .email, .de, .solutions)</li>
|
||||
<li>APPLICATION refers to all downloadable or installable content which can therfore be used on an a given DEVICE.</li>
|
||||
<li>You means the individual accessing or using the SERVICES, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Acknowledgement</h2>
|
||||
<p>These are the TERMS governing the use of this SERVICE and the agreement that operates between You and the COMPANY. These TERMS set out the rights and obligations of all users regarding the use of the SERVICE.</p>
|
||||
<p>Your access to and use of the SERVICE is conditioned on Your acceptance of and compliance with these TERMS. These TERMS apply to all visitors, users and others who access or use the SERVICE.</p>
|
||||
<p>By accessing or using the SERVICE You agree to be bound by these TERMS. If You disagree with any part of these TERMS then You may not access the SERVICE.<p>
|
||||
<p>You represent that you are at least over the age of 18 and be over the Age of Majority. The COMPANY does not permit those under 18 or the Age of Majurity to use the SERVICE.</p>
|
||||
<p>Your access to and use of the SERVICE is also conditioned on Your acceptance of and compliance with the Privacy Policy of the COMPANY. Our Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your personal information when You use the Application or the WEBSITE and tells You about Your privacy rights and how the law protects You. Please read Our Privacy Policy carefully before using Our SERVICE.</p>
|
||||
|
||||
<h2>Copyright</h2>
|
||||
<p>Unless otherwise noted, all materials including without limitation, logos, brand names, images, designs, photographs, videos, audio, source code and written and other materials that appear as part of our WEBSITE are copyrights, trademarks, service marks, trade dress and/or other intellectual property whether registered or unregistered ("Intellectual Property") owned, controlled or licensed by Orange-Management. Our WEBSITE as a whole is protected by copyright and trade dress. Nothing on our WEBSITE should be construed as granting, by implication, estoppel or otherwise, any license or right to use any Intellectual Property displayed or used on our WEBSITE, without the prior written permission of the Intellectual Property owner. Orange-Management aggressively enforces its intellectual property rights to the fullest extent of the law. The names and logos of Orange-Management, may not be used in any way, including in advertising or publicity pertaining to distribution of materials on our WEBSITE, without prior, written permission from Orange-Management. Orange-Management prohibits use of any logo of Orange-Management or any of its affiliates as part of a link to or from any WEBSITE unless Orange-Management approves such link in advance and in writing. Fair use of Orange-Management Intellectual Property requires proper acknowledgment. Other product and company names mentioned in our Website may be the Intellectual Property of their respective owners.</p>
|
||||
|
||||
<h2>Links</h2>
|
||||
<p>Our SERVICE may contain links to third-party web sites or services that are not owned or controlled by the COMPANY.</p>
|
||||
<p>The COMPANY has no control over, and assumes no responsibility for, the contentthird-party web sites or services that You visit.</p>
|
||||
|
||||
<h2>Termination</h2>
|
||||
<p>We may terminate or suspend Your access immediately, without prior notice or liability, for any reason whatsoever, including without limitation if You breach these TERMS.</p>
|
||||
<p>Upon termination, Your right to use the SERVICE will cease immediately.</p>
|
||||
|
||||
<h2>Limitation of Liability</h2>
|
||||
<p>Notwithstanding any damages that You might incur, the entire liability of the COMPANY and any of its suppliers under any provision of this TERMS and Your exclusive remedy for all of the foregoing shall be limited to the amount actually paid by through the SERVICE.</p>
|
||||
<p>To the maximum extent permitted by applicable law, in no event shall the COMPANY or its suppliers be liable for any special, incidental, indirect, or consequential damages whatsoever (including, but not limited to, damages for loss of profits, loss of data or other information, for business interruption, for personal injury, loss of privacy arising out of or in any way related to the use of or inability to use the SERVICE, third-party software and/or third-party hardware used with the SERVICE, or otherwise in connection with any provision of this TERMS), even if the COMPANY or any supplier has been advised of the possibility of such damages and even if the remedy fails of its essential purpose.</p>
|
||||
<p>Some states or countries do not allow the exclusion of implied warranties or limitation of liability for incidental or consequential damages, which means that some of the above limitations may not apply. In these states or countries, each party's liability will be limited to the greatest extent permitted by law.</p>
|
||||
|
||||
<h2>Disclaimer</h2>
|
||||
<p>The SERVICE is provided to You "AS IS" and "AS AVAILABLE" and with all faults and defects without warranty of any kind. To the maximum extent permitted under applicable law, the COMPANY, on its own behalf and on behalf of its AFFILIATES and its and their respective licensors and service providers, expressly disclaims all warranties, whether express, implied, statutory or otherwise, with respect to the SERVICE, including all implied warranties of merchantability, fitness for a particular purpose, title and non-infringement, and warranties that may arise out of course of dealing, course of performance, usage or trade practice. Without limitation to the foregoing, the COMPANY provides no warranty or undertaking, and makes no representation of any kind that the SERVICE will meet Your requirements, achieve any intended results, be compatible or work with any other software, applications, systems or services, operate without interruption, meet any performance or reliability standards or be error free or that any errors or defects can or will be corrected.</p>
|
||||
<p>Without limiting the foregoing, neither the COMPANY nor any of the company's provider makes any representation or warranty of any kind, express or implied: (i) as to the operation or availability of the SERVICE, or the information, content, and materials or products included thereon; (ii) that the SERVICE will be uninterrupted or error-free; (iii) as to the accuracy, reliability, or currency of any information or content provided through the SERVICE; or (iv) that the SERVICE, its servers, the content, or e-mails sent from or on behalf of the COMPANY are free of viruses, scripts, trojan horses, worms, malware, timebombs or other harmful components.</p>
|
||||
<p>Some jurisdictions do not allow the exclusion of certain types of warranties or limitations on applicable statutory rights of a consumer, so some or all of the above exclusions and limitations may not apply to You. But in such a case the exclusions and limitations set forth in this section shall be applied to the greatest extent enforceable under applicable law.</p>
|
||||
|
||||
<h2>Governing Law</h2>
|
||||
<p>The laws of the COUNTRY, excluding its conflicts of law rules, shall govern these TERMS and Your use of the SERVICE. Your use of the APPLICATION may also be subject to other local, state, national, or international laws.</p>
|
||||
<p>The ineffectiveness of one or more provisions of this agreement does not affect the validity of the others. Each party to these TERMS can in this case demand that a new valid provision be agreed which best achieves the economic purpose of the ineffective provision.</p>
|
||||
|
||||
<h2>Dispute Resolution</h2>
|
||||
<p>If You have any concern or dispute about the Service, You agree to first try to resolve the dispute informally by contacting the COMPANY.</p>
|
||||
|
||||
<h2>United States Legal Compliance</h2>
|
||||
<p>You represent and warrant that (i) You are not located in a country that is subject to the United States government embargo, or that has been designated by the United States government as a "terrorist supporting" country, and (ii) You are not listed on any United States government list of prohibited or restricted parties.</p>
|
||||
|
||||
<h2>Changes to these Terms</h2>
|
||||
<p>We reserve the right, at Our sole discretion, to modify or replace these TERMS at any time. If a revision is material We will make reasonable efforts to provide at least 30 days' notice prior to any new terms taking effect. What constitutes a material change will be determined at Our sole discretion.</p>
|
||||
<p>By continuing to access or use Our SERVICE after those revisions become effective, You agree to be bound by the revised terms. If You do not agree to the new terms, in whole or in part, please stop using the WEBSITE and the SERVICE.</p>
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>For questions regarding these TERMS please feel free to contact us at info@orange-management.email</p>, privacy policies, or practices of any third party websites or services. You further acknowledge and agree that the COMPANY shall not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with the use of or reliance on any such content, goods or services available on or through any such websites or services.</p>
|
||||
<p>We strongly advise You to read the terms and conditions and privacy policies of any third-party web sites or services that You visit.</p>
|
||||
|
||||
<h2>Termination</h2>
|
||||
<p>We may terminate or suspend Your access immediately, without prior notice or liability, for any reason whatsoever, including without limitation if You breach these TERMS.</p>
|
||||
<p>Upon termination, Your right to use the SERVICE will cease immediately.</p>
|
||||
|
||||
<h2>Limitation of Liability</h2>
|
||||
<p>Notwithstanding any damages that You might incur, the entire liability of the COMPANY and any of its suppliers under any provision of this TERMS and Your exclusive remedy for all of the foregoing shall be limited to the amount actually paid by through the SERVICE.</p>
|
||||
<p>To the maximum extent permitted by applicable law, in no event shall the COMPANY or its suppliers be liable for any special, incidental, indirect, or consequential damages whatsoever (including, but not limited to, damages for loss of profits, loss of data or other information, for business interruption, for personal injury, loss of privacy arising out of or in any way related to the use of or inability to use the SERVICE, third-party software and/or third-party hardware used with the SERVICE, or otherwise in connection with any provision of this TERMS), even if the COMPANY or any supplier has been advised of the possibility of such damages and even if the remedy fails of its essential purpose.</p>
|
||||
<p>Some states or countries do not allow the exclusion of implied warranties or limitation of liability for incidental or consequential damages, which means that some of the above limitations may not apply. In these states or countries, each party's liability will be limited to the greatest extent permitted by law.</p>
|
||||
|
||||
<h2>Disclaimer</h2>
|
||||
<p>The SERVICE is provided to You "AS IS" and "AS AVAILABLE" and with all faults and defects without warranty of any kind. To the maximum extent permitted under applicable law, the COMPANY, on its own behalf and on behalf of its AFFILIATES and its and their respective licensors and service providers, expressly disclaims all warranties, whether express, implied, statutory or otherwise, with respect to the SERVICE, including all implied warranties of merchantability, fitness for a particular purpose, title and non-infringement, and warranties that may arise out of course of dealing, course of performance, usage or trade practice. Without limitation to the foregoing, the COMPANY provides no warranty or undertaking, and makes no representation of any kind that the SERVICE will meet Your requirements, achieve any intended results, be compatible or work with any other software, applications, systems or services, operate without interruption, meet any performance or reliability standards or be error free or that any errors or defects can or will be corrected.</p>
|
||||
<p>Without limiting the foregoing, neither the COMPANY nor any of the company's provider makes any representation or warranty of any kind, express or implied: (i) as to the operation or availability of the SERVICE, or the information, content, and materials or products included thereon; (ii) that the SERVICE will be uninterrupted or error-free; (iii) as to the accuracy, reliability, or currency of any information or content provided through the SERVICE; or (iv) that the SERVICE, its servers, the content, or e-mails sent from or on behalf of the COMPANY are free of viruses, scripts, trojan horses, worms, malware, timebombs or other harmful components.</p>
|
||||
<p>Some jurisdictions do not allow the exclusion of certain types of warranties or limitations on applicable statutory rights of a consumer, so some or all of the above exclusions and limitations may not apply to You. But in such a case the exclusions and limitations set forth in this section shall be applied to the greatest extent enforceable under applicable law.</p>
|
||||
|
||||
<h2>Governing Law</h2>
|
||||
<p>The laws of the COUNTRY, excluding its conflicts of law rules, shall govern these TERMS and Your use of the SERVICE. Your use of the APPLICATION may also be subject to other local, state, national, or international laws.</p>
|
||||
<p>The ineffectiveness of one or more provisions of this agreement does not affect the validity of the others. Each party to these TERMS can in this case demand that a new valid provision be agreed which best achieves the economic purpose of the ineffective provision.</p>
|
||||
|
||||
<h2>Dispute Resolution</h2>
|
||||
<p>If You have any concern or dispute about the Service, You agree to first try to resolve the dispute informally by contacting the COMPANY.</p>
|
||||
|
||||
<h2>United States Legal Compliance</h2>
|
||||
<p>You represent and warrant that (i) You are not located in a country that is subject to the United States government embargo, or that has been designated by the United States government as a "terrorist supporting" country, and (ii) You are not listed on any United States government list of prohibited or restricted parties.</p>
|
||||
|
||||
<h2>Changes to these Terms</h2>
|
||||
<p>We reserve the right, at Our sole discretion, to modify or replace these TERMS at any time. If a revision is material We will make reasonable efforts to provide at least 30 days' notice prior to any new terms taking effect. What constitutes a material change will be determined at Our sole discretion.</p>
|
||||
<p>By continuing to access or use Our SERVICE after those revisions become effective, You agree to be bound by the revised terms. If You do not agree to the new terms, in whole or in part, please stop using the WEBSITE and the SERVICE.</p>
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>For questions regarding these TERMS please feel free to contact us at info@orange-management.email</p>
|
||||
</div>
|
||||
</div>
|
||||
58
Admin/Install/Application/QA/index.tpl.php
Executable file
58
Admin/Install/Application/QA/index.tpl.php
Executable file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
*
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use phpOMS\Uri\UriFactory;
|
||||
|
||||
/** @var phpOMS\Model\Html\Head $head */
|
||||
$head = $this->getData('head');
|
||||
|
||||
/** @var array $dispatch */
|
||||
$dispatch = $this->getData('dispatch') ?? [];
|
||||
?>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="<?= $this->printHtml($this->response->getLanguage()); ?>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#262626">
|
||||
<meta name="msapplication-navbutton-color" content="#262626">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="#262626">
|
||||
<meta name="description" content="<?= $this->getHtml(':meta', '0', '0'); ?>">
|
||||
<?= $head->render(); ?>
|
||||
|
||||
<base href="<?= UriFactory::build('{/base}'); ?>/">
|
||||
|
||||
<link rel="manifest" href="<?= UriFactory::build('Web/{APPNAME}/manifest.json'); ?>">
|
||||
<link rel="shortcut icon" href="<?= UriFactory::build('Web/{APPNAME}/img/favicon.ico'); ?>" type="image/x-icon">
|
||||
|
||||
<title><?= $this->printHtml($head->title); ?></title>
|
||||
|
||||
<?= $head->renderAssets(); ?>
|
||||
|
||||
<style><?= $head->renderStyle(); ?></style>
|
||||
<script><?= $head->renderScript(); ?></script>
|
||||
</head>
|
||||
<body>
|
||||
<?php include __DIR__ . '/tpl/header.tpl.php'; ?>
|
||||
<main>
|
||||
<?php
|
||||
foreach ($dispatch as $view) {
|
||||
if ($view instanceof \phpOMS\Contract\RenderableInterface) {
|
||||
echo $view->render();
|
||||
}
|
||||
}
|
||||
?>
|
||||
</main>
|
||||
<?php include __DIR__ . '/tpl/footer.tpl.php'; ?>
|
||||
20
Admin/Install/Application/QA/info.json
Executable file
20
Admin/Install/Application/QA/info.json
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": {
|
||||
"id": 1007700001,
|
||||
"internal": "{APPNAME}",
|
||||
"external": "{APPNAME}"
|
||||
},
|
||||
"category": "Web",
|
||||
"version": "1.0.0",
|
||||
"requirements": {
|
||||
"phpOMS": "1.0.0",
|
||||
"phpOMS-db": "1.0.0"
|
||||
},
|
||||
"creator": {
|
||||
"name": "Orange Management",
|
||||
"website": "www.spl1nes.com"
|
||||
},
|
||||
"description": "The shop application.",
|
||||
"directory": "Shop",
|
||||
"dependencies": {}
|
||||
}
|
||||
5
Admin/Install/Application/QA/js/qa.js
Executable file
5
Admin/Install/Application/QA/js/qa.js
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
jsOMS.ready(function ()
|
||||
{
|
||||
"use strict";
|
||||
|
||||
});
|
||||
19
Admin/Install/Application/QA/lang/en.lang.php
Executable file
19
Admin/Install/Application/QA/lang/en.lang.php
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Web\{APPNAME}
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
*
|
||||
* @version 1.0.0
|
||||
*
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
return [[
|
||||
':meta' => 'Demo Shop.',
|
||||
]];
|
||||
75
Admin/Install/Application/QA/manifest.json
Executable file
75
Admin/Install/Application/QA/manifest.json
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"lang": "en",
|
||||
"dir": "ltr",
|
||||
"start_url": "../../{APPNAME}",
|
||||
"type": "privileged",
|
||||
"name": "Orange Management Shop",
|
||||
"description": "OMS shop application.",
|
||||
"short_name": "OMS Shop",
|
||||
"icons": [
|
||||
{
|
||||
"src": "img/maskable_icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
],
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "any",
|
||||
"theme_color": "#343a40",
|
||||
"background_color": "white",
|
||||
"permissions": {
|
||||
"audio-capture" : {
|
||||
"description" : "Audio capture"
|
||||
},
|
||||
"video-capture": {
|
||||
"description": "Video capture"
|
||||
},
|
||||
"speech-recognition" : {
|
||||
"description" : "Speech recognition"
|
||||
}
|
||||
}
|
||||
}
|
||||
75
Admin/Install/Application/QA/manifest.webmanifest
Executable file
75
Admin/Install/Application/QA/manifest.webmanifest
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"lang": "en",
|
||||
"dir": "ltr",
|
||||
"start_url": "../../{APPNAME}",
|
||||
"type": "privileged",
|
||||
"name": "Orange Management Shop",
|
||||
"description": "OMS shop application.",
|
||||
"short_name": "OMS Shop",
|
||||
"icons": [
|
||||
{
|
||||
"src": "img/maskable_icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "img/maskable_icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
],
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "any",
|
||||
"theme_color": "#343a40",
|
||||
"background_color": "white",
|
||||
"permissions": {
|
||||
"audio-capture" : {
|
||||
"description" : "Audio capture"
|
||||
},
|
||||
"video-capture": {
|
||||
"description": "Video capture"
|
||||
},
|
||||
"speech-recognition" : {
|
||||
"description" : "Speech recognition"
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Admin/Install/CMS.install.json
Executable file
7
Admin/Install/CMS.install.json
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
[
|
||||
{
|
||||
"src": "Modules/QA/Admin/Install/Application/QA",
|
||||
"dest": "Web/QA",
|
||||
"name": "QA"
|
||||
}
|
||||
]
|
||||
45
Admin/Install/CMS.php
Executable file
45
Admin/Install/CMS.php
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Modules\QA\Admin\Install
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QA\Admin\Install;
|
||||
|
||||
use Model\Setting;
|
||||
use Model\SettingMapper;
|
||||
use phpOMS\Application\ApplicationAbstract;
|
||||
|
||||
/**
|
||||
* CMS class.
|
||||
*
|
||||
* @package Modules\QA\Admin\Install
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class CMS
|
||||
{
|
||||
/**
|
||||
* Install media providing
|
||||
*
|
||||
* @param string $path Module path
|
||||
* @param ApplicationAbstract $app Application
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function install(string $path, ApplicationAbstract $app) : void
|
||||
{
|
||||
$app = \Modules\CMS\Admin\Installer::installExternal($app, ['path' => __DIR__ . '/CMS.install.json']);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +1,18 @@
|
|||
{
|
||||
"qa_category": {
|
||||
"name": "qa_category",
|
||||
"qa_app": {
|
||||
"name": "qa_app",
|
||||
"fields": {
|
||||
"qa_category_id": {
|
||||
"name": "qa_category_id",
|
||||
"qa_app_id": {
|
||||
"name": "qa_app_id",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"primary": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"qa_category_parent": {
|
||||
"name": "qa_category_parent",
|
||||
"type": "INT",
|
||||
"default": null,
|
||||
"null": true,
|
||||
"foreignTable": "qa_category",
|
||||
"foreignKey": "qa_category_id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"qa_category_l11n": {
|
||||
"name": "qa_category_l11n",
|
||||
"fields": {
|
||||
"qa_category_l11n_id": {
|
||||
"name": "qa_category_l11n_id",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"primary": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"qa_category_l11n_name": {
|
||||
"name": "qa_category_l11n_name",
|
||||
"qa_app_name": {
|
||||
"name": "qa_app_name",
|
||||
"type": "VARCHAR(255)",
|
||||
"null": false
|
||||
},
|
||||
"qa_category_l11n_category": {
|
||||
"name": "qa_category_l11n_category",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"foreignTable": "qa_category",
|
||||
"foreignKey": "qa_category_id"
|
||||
},
|
||||
"qa_category_l11n_language": {
|
||||
"name": "qa_category_l11n_language",
|
||||
"type": "VARCHAR(2)",
|
||||
"default": null,
|
||||
"null": true,
|
||||
"foreignTable": "language",
|
||||
"foreignKey": "language_639_1"
|
||||
"default": null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -64,8 +29,7 @@
|
|||
"qa_question_status": {
|
||||
"name": "qa_question_status",
|
||||
"type": "INT",
|
||||
"default": null,
|
||||
"null": true
|
||||
"null": false
|
||||
},
|
||||
"qa_question_title": {
|
||||
"name": "qa_question_title",
|
||||
|
|
@ -99,13 +63,12 @@
|
|||
"foreignTable": "account",
|
||||
"foreignKey": "account_id"
|
||||
},
|
||||
"qa_question_category": {
|
||||
"name": "qa_question_category",
|
||||
"qa_question_app": {
|
||||
"name": "qa_question_app",
|
||||
"type": "INT",
|
||||
"default": null,
|
||||
"null": true,
|
||||
"foreignTable": "qa_category",
|
||||
"foreignKey": "qa_category_id"
|
||||
"null": false,
|
||||
"foreignTable": "qa_app",
|
||||
"foreignKey": "qa_app_id"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,7 +14,12 @@ declare(strict_types=1);
|
|||
|
||||
namespace Modules\QA\Admin;
|
||||
|
||||
use Modules\QA\Models\QAApp;
|
||||
use Modules\QA\Models\QAAppMapper;
|
||||
use phpOMS\Config\SettingsInterface;
|
||||
use phpOMS\DataStorage\Database\DatabasePool;
|
||||
use phpOMS\Module\InstallerAbstract;
|
||||
use phpOMS\Module\ModuleInfo;
|
||||
|
||||
/**
|
||||
* Installer class.
|
||||
|
|
@ -26,4 +31,16 @@ use phpOMS\Module\InstallerAbstract;
|
|||
*/
|
||||
final class Installer extends InstallerAbstract
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function install(DatabasePool $dbPool, ModuleInfo $info, SettingsInterface $cfgHandler) : void
|
||||
{
|
||||
parent::install($dbPool, $info, $cfgHandler);
|
||||
|
||||
$app = new QAApp();
|
||||
$app->name = 'Backend';
|
||||
|
||||
$id = QAAppMapper::create($app);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
Admin/Routes/Web/Api.php
Normal file → Executable file
10
Admin/Routes/Web/Api.php
Normal file → Executable file
|
|
@ -6,23 +6,23 @@ use phpOMS\Account\PermissionType;
|
|||
use phpOMS\Router\RouteVerb;
|
||||
|
||||
return [
|
||||
'^.*/qa/category(\?.*|$)' => [
|
||||
'^.*/qa/app(\?.*|$)' => [
|
||||
[
|
||||
'dest' => '\Modules\QA\Controller\ApiController:apiQACategoryCreate',
|
||||
'dest' => '\Modules\QA\Controller\ApiController:apiQAAppCreate',
|
||||
'verb' => RouteVerb::PUT,
|
||||
'permission' => [
|
||||
'module' => ApiController::MODULE_NAME,
|
||||
'type' => PermissionType::CREATE,
|
||||
'state' => PermissionState::CATEGORY,
|
||||
'state' => PermissionState::APP,
|
||||
],
|
||||
],
|
||||
[
|
||||
'dest' => '\Modules\QA\Controller\ApiController:apiQACategoryUpdate',
|
||||
'dest' => '\Modules\QA\Controller\ApiController:apiQAAppUpdate',
|
||||
'verb' => RouteVerb::SET,
|
||||
'permission' => [
|
||||
'module' => ApiController::MODULE_NAME,
|
||||
'type' => PermissionType::CREATE,
|
||||
'state' => PermissionState::CATEGORY,
|
||||
'state' => PermissionState::APP,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Modules\QA\Controller;
|
|||
use Modules\Admin\Models\NullAccount;
|
||||
use Modules\Profile\Models\Profile;
|
||||
use Modules\QA\Models\NullQAAnswerVote;
|
||||
use Modules\QA\Models\NullQACategory;
|
||||
use Modules\QA\Models\NullQAApp;
|
||||
use Modules\QA\Models\NullQAQuestion;
|
||||
use Modules\QA\Models\NullQAQuestionVote;
|
||||
use Modules\QA\Models\QAAnswer;
|
||||
|
|
@ -25,10 +25,8 @@ use Modules\QA\Models\QAAnswerMapper;
|
|||
use Modules\QA\Models\QAAnswerStatus;
|
||||
use Modules\QA\Models\QAAnswerVote;
|
||||
use Modules\QA\Models\QAAnswerVoteMapper;
|
||||
use Modules\QA\Models\QACategory;
|
||||
use Modules\QA\Models\QACategoryL11n;
|
||||
use Modules\QA\Models\QACategoryL11nMapper;
|
||||
use Modules\QA\Models\QACategoryMapper;
|
||||
use Modules\QA\Models\QAApp;
|
||||
use Modules\QA\Models\QAAppMapper;
|
||||
use Modules\QA\Models\QAQuestion;
|
||||
use Modules\QA\Models\QAQuestionMapper;
|
||||
use Modules\QA\Models\QAQuestionStatus;
|
||||
|
|
@ -44,7 +42,7 @@ use phpOMS\Model\Message\FormValidation;
|
|||
use phpOMS\Utils\Parser\Markdown\Markdown;
|
||||
|
||||
/**
|
||||
* Task class.
|
||||
* QA api controller class.
|
||||
*
|
||||
* @package Modules\QA
|
||||
* @license OMS License 1.0
|
||||
|
|
@ -83,7 +81,7 @@ final class ApiController extends Controller
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiQACategoryUpdate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
public function apiQAAppUpdate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -150,8 +148,8 @@ final class ApiController extends Controller
|
|||
$question->name = (string) $request->getData('title');
|
||||
$question->questionRaw = (string) $request->getData('plain');
|
||||
$question->question = Markdown::parse((string) ($request->getData('plain') ?? ''));
|
||||
$question->app = new NullQAApp((int) ($request->getData('app') ?? 1));
|
||||
$question->setLanguage((string) $request->getData('language'));
|
||||
$question->setCategory(new NullQACategory((int) $request->getData('category')));
|
||||
$question->setStatus((int) $request->getData('status'));
|
||||
$question->createdBy = new Profile(new NullAccount($request->header->account));
|
||||
|
||||
|
|
@ -190,7 +188,6 @@ final class ApiController extends Controller
|
|||
if (($val['title'] = empty($request->getData('title')))
|
||||
|| ($val['plain'] = empty($request->getData('plain')))
|
||||
|| ($val['language'] = empty($request->getData('language')))
|
||||
|| ($val['category'] = empty($request->getData('category')))
|
||||
|| ($val['status'] = (
|
||||
$request->getData('status') !== null
|
||||
&& !QAQuestionStatus::isValidValue((int) $request->getData('status'))
|
||||
|
|
@ -329,45 +326,40 @@ final class ApiController extends Controller
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiQACategoryCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
public function apiQAAppCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
{
|
||||
if (!empty($val = $this->validateQACategoryCreate($request))) {
|
||||
$response->set('qa_category_create', new FormValidation($val));
|
||||
if (!empty($val = $this->validateQAAppCreate($request))) {
|
||||
$response->set('qa_app_create', new FormValidation($val));
|
||||
$response->header->status = RequestStatusCode::R_400;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$category = $this->createQACategoryFromRequest($request);
|
||||
$category->setL11n($request->getData('name'), $request->getData('language'));
|
||||
$this->createModel($request->header->account, $category, QACategoryMapper::class, 'category', $request->getOrigin());
|
||||
$app = $this->createQAAppFromRequest($request);
|
||||
$this->createModel($request->header->account, $app, QAAppMapper::class, 'app', $request->getOrigin());
|
||||
|
||||
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Category', 'Category successfully created.', $category);
|
||||
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'App', 'App successfully created.', $app);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create category from request.
|
||||
* Method to create app from request.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return QACategory Returns the created category from the request
|
||||
* @return QAApp Returns the created app from the request
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function createQACategoryFromRequest(RequestAbstract $request) : QACategory
|
||||
public function createQAAppFromRequest(RequestAbstract $request) : QAApp
|
||||
{
|
||||
$category = new QACategory();
|
||||
//$category->setApp(new NullQAApp((int) ($request->getData('app') ?? 1)));
|
||||
$app = new QAApp();
|
||||
$app->name = $request->getData('name') ?? '';
|
||||
|
||||
if ($request->getData('parent') !== null) {
|
||||
$category->parent = new NullQACategory((int) $request->getData('parent'));
|
||||
}
|
||||
|
||||
return $category;
|
||||
return $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate category create request
|
||||
* Validate app create request
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
|
|
@ -375,7 +367,7 @@ final class ApiController extends Controller
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function validateQACategoryCreate(RequestAbstract $request) : array
|
||||
private function validateQAAppCreate(RequestAbstract $request) : array
|
||||
{
|
||||
$val = [];
|
||||
if (($val['name'] = empty($request->getData('name')))) {
|
||||
|
|
@ -385,76 +377,6 @@ final class ApiController extends Controller
|
|||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate tag l11n create request
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function validateQACategoryL11nCreate(RequestAbstract $request) : array
|
||||
{
|
||||
$val = [];
|
||||
if (($val['name'] = empty($request->getData('name')))
|
||||
|| ($val['category'] = empty($request->getData('category')))
|
||||
) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to create tag localization
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $data Generic data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiQACategoryL11nCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
{
|
||||
if (!empty($val = $this->validateQACategoryL11nCreate($request))) {
|
||||
$response->set('qa_category_l11n_create', new FormValidation($val));
|
||||
$response->header->status = RequestStatusCode::R_400;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$l11nQACategory = $this->createQACategoryL11nFromRequest($request);
|
||||
$this->createModel($request->header->account, $l11nQACategory, QACategoryL11nMapper::class, 'qa_category_l11n', $request->getOrigin());
|
||||
|
||||
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Localization', 'Category localization successfully created', $l11nQACategory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create tag localization from request.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return QACategoryL11n
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function createQACategoryL11nFromRequest(RequestAbstract $request) : QACategoryL11n
|
||||
{
|
||||
$l11nQACategory = new QACategoryL11n();
|
||||
$l11nQACategory->setCategory((int) ($request->getData('category') ?? 0));
|
||||
$l11nQACategory->setLanguage((string) (
|
||||
$request->getData('language') ?? $request->getLanguage()
|
||||
));
|
||||
$l11nQACategory->name = (string) ($request->getData('name') ?? '');
|
||||
|
||||
return $l11nQACategory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to change question vote
|
||||
*
|
||||
|
|
|
|||
|
|
@ -15,14 +15,16 @@ declare(strict_types=1);
|
|||
namespace Modules\QA\Controller;
|
||||
|
||||
use Modules\QA\Models\QAQuestionMapper;
|
||||
use Modules\QA\Models\QAAppMapper;
|
||||
use phpOMS\Asset\AssetType;
|
||||
use phpOMS\Contract\RenderableInterface;
|
||||
use phpOMS\Message\RequestAbstract;
|
||||
use phpOMS\Message\ResponseAbstract;
|
||||
use phpOMS\Views\View;
|
||||
use Modules\QA\Models\QAHelperMapper;
|
||||
|
||||
/**
|
||||
* Task class.
|
||||
* QA backend controller class.
|
||||
*
|
||||
* @package Modules\QA
|
||||
* @license OMS License 1.0
|
||||
|
|
@ -70,6 +72,9 @@ final class BackendController extends Controller
|
|||
$list = QAQuestionMapper::with('language', $response->getLanguage())::getNewest(50);
|
||||
$view->setData('questions', $list);
|
||||
|
||||
$apps = QAAppMapper::getAll();
|
||||
$view->setData('apps', $apps);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +99,9 @@ final class BackendController extends Controller
|
|||
$question = QAQuestionMapper::get((int) $request->getData('id'));
|
||||
$view->addData('question', $question);
|
||||
|
||||
$scores = QAHelperMapper::getAccountScore($question->getAccounts());
|
||||
$view->addData('scores', $scores);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Modules\QA\Controller;
|
|||
use phpOMS\Module\ModuleAbstract;
|
||||
|
||||
/**
|
||||
* Task class.
|
||||
* QA controller class.
|
||||
*
|
||||
* @package Modules\QA
|
||||
* @license OMS License 1.0
|
||||
|
|
|
|||
0
Models/NullQAAnswerVote.php
Normal file → Executable file
0
Models/NullQAAnswerVote.php
Normal file → Executable file
38
Models/NullQAApp.php
Normal file
38
Models/NullQAApp.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
/**
|
||||
* Null model class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class NullQAApp extends QAApp
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $id Model id
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(int $id = 0)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
}
|
||||
0
Models/NullQAQuestionVote.php
Normal file → Executable file
0
Models/NullQAQuestionVote.php
Normal file → Executable file
|
|
@ -34,5 +34,5 @@ abstract class PermissionState extends Enum
|
|||
|
||||
public const VOTE = 4;
|
||||
|
||||
public const CATEGORY = 5;
|
||||
public const APP = 5;
|
||||
}
|
||||
|
|
|
|||
2
Models/QAAnswerVote.php
Normal file → Executable file
2
Models/QAAnswerVote.php
Normal file → Executable file
|
|
@ -18,7 +18,7 @@ use Modules\Admin\Models\Account;
|
|||
use Modules\Admin\Models\NullAccount;
|
||||
|
||||
/**
|
||||
* Task class.
|
||||
* QA answer vote class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
|
|
|
|||
4
Models/QAAnswerVoteMapper.php
Normal file → Executable file
4
Models/QAAnswerVoteMapper.php
Normal file → Executable file
|
|
@ -84,11 +84,11 @@ final class QAAnswerVoteMapper extends DataMapperAbstract
|
|||
* @param int $answer Answer id
|
||||
* @param int $account Account id
|
||||
*
|
||||
* @return QAAnswerVote
|
||||
* @return bool|QAAnswerVote
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function findVote(int $answer, int $account) : QAAnswerVote
|
||||
public static function findVote(int $answer, int $account) : bool|QAAnswerVote
|
||||
{
|
||||
$depth = 3;
|
||||
$query = self::getQuery();
|
||||
|
|
|
|||
73
Models/QAApp.php
Normal file
73
Models/QAApp.php
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
/**
|
||||
* QA app class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class QAApp implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* ID.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected int $id = 0;
|
||||
|
||||
/**
|
||||
* Application name.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public string $name = '';
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int Model id
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getId() : int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toArray() : array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
}
|
||||
14
Models/QACategoryL11nMapper.php → Models/QAAppMapper.php
Executable file → Normal file
14
Models/QACategoryL11nMapper.php → Models/QAAppMapper.php
Executable file → Normal file
|
|
@ -17,14 +17,14 @@ namespace Modules\QA\Models;
|
|||
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
||||
|
||||
/**
|
||||
* Category mapper class.
|
||||
* Mapper class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class QACategoryL11nMapper extends DataMapperAbstract
|
||||
final class QAAppMapper extends DataMapperAbstract
|
||||
{
|
||||
/**
|
||||
* Columns.
|
||||
|
|
@ -33,10 +33,8 @@ final class QACategoryL11nMapper extends DataMapperAbstract
|
|||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $columns = [
|
||||
'qa_category_l11n_id' => ['name' => 'qa_category_l11n_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'qa_category_l11n_name' => ['name' => 'qa_category_l11n_name', 'type' => 'string', 'internal' => 'name', 'autocomplete' => true],
|
||||
'qa_category_l11n_category' => ['name' => 'qa_category_l11n_category', 'type' => 'int', 'internal' => 'category'],
|
||||
'qa_category_l11n_language' => ['name' => 'qa_category_l11n_language', 'type' => 'string', 'internal' => 'language'],
|
||||
'qa_app_id' => ['name' => 'qa_app_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'qa_app_name' => ['name' => 'qa_app_name', 'type' => 'string', 'internal' => 'name'],
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -45,7 +43,7 @@ final class QACategoryL11nMapper extends DataMapperAbstract
|
|||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static string $table = 'qa_category_l11n';
|
||||
protected static string $table = 'qa_app';
|
||||
|
||||
/**
|
||||
* Primary field name.
|
||||
|
|
@ -53,5 +51,5 @@ final class QACategoryL11nMapper extends DataMapperAbstract
|
|||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static string $primaryField = 'qa_category_l11n_id';
|
||||
protected static string $primaryField = 'qa_app_id';
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
use phpOMS\Localization\ISO639x1Enum;
|
||||
|
||||
/**
|
||||
* Task class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class QACategory implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* ID.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected int $id = 0;
|
||||
|
||||
/**
|
||||
* Name.
|
||||
*
|
||||
* @var string|QACategoryL11n
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private $name = '';
|
||||
|
||||
/**
|
||||
* Parent category.
|
||||
*
|
||||
* @var QACategory
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public self $parent;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @sicne 1.0.0
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->parent = new NullQACategory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int Model id
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getId() : int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getL11n() : string
|
||||
{
|
||||
return $this->name instanceof QACategoryL11n ? $this->name->getName() : $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param string|QACategoryL11n $name Category name
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setL11n($name, string $lang = ISO639x1Enum::_EN) : void
|
||||
{
|
||||
if ($name instanceof QACategoryL11n) {
|
||||
$this->name = $name;
|
||||
} elseif ($this->name instanceof QACategoryL11n && \is_string($name)) {
|
||||
$this->name->name = $name;
|
||||
} elseif (\is_string($name)) {
|
||||
$this->name = new QACategoryL11n();
|
||||
$this->name->name = $name;
|
||||
$this->name->setLanguage($lang);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize() : array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
use phpOMS\Contract\ArrayableInterface;
|
||||
use phpOMS\Localization\ISO639x1Enum;
|
||||
|
||||
/**
|
||||
* Category class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class QACategoryL11n implements \JsonSerializable, ArrayableInterface
|
||||
{
|
||||
/**
|
||||
* Article ID.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected int $id = 0;
|
||||
|
||||
/**
|
||||
* Category ID.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected int $category = 0;
|
||||
|
||||
/**
|
||||
* Language.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected string $language = ISO639x1Enum::_EN;
|
||||
|
||||
/**
|
||||
* Name.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public string $name = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name Name
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(string $name = '', string $language = ISO639x1Enum::_EN)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->language = $language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getId() : int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set category.
|
||||
*
|
||||
* @param int $category Category id
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setCategory(int $category) : void
|
||||
{
|
||||
$this->category = $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getCategory() : int
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get language
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getLanguage() : string
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set language
|
||||
*
|
||||
* @param string $language Language
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setLanguage(string $language) : void
|
||||
{
|
||||
$this->language = $language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getName() : string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toArray() : array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'category' => $this->category,
|
||||
'language' => $this->language,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
||||
|
||||
/**
|
||||
* Mapper class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class QACategoryMapper extends DataMapperAbstract
|
||||
{
|
||||
/**
|
||||
* Columns.
|
||||
*
|
||||
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $columns = [
|
||||
'qa_category_id' => ['name' => 'qa_category_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'qa_category_parent' => ['name' => 'qa_category_parent', 'type' => 'int', 'internal' => 'parent'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Belongs to.
|
||||
*
|
||||
* @var array<string, array{mapper:string, external:string}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $belongsTo = [
|
||||
'parent' => [
|
||||
'mapper' => self::class,
|
||||
'external' => 'qa_category_parent',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Has many relation.
|
||||
*
|
||||
* @var array<string, array{mapper:string, table:string, self?:?string, external?:?string, column?:string}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $hasMany = [
|
||||
'name' => [
|
||||
'mapper' => QACategoryL11nMapper::class,
|
||||
'table' => 'qa_category_l11n',
|
||||
'self' => 'qa_category_l11n_category',
|
||||
'column' => 'name',
|
||||
'conditional' => true,
|
||||
'external' => null,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static string $table = 'qa_category';
|
||||
|
||||
/**
|
||||
* Primary field name.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static string $primaryField = 'qa_category_id';
|
||||
}
|
||||
74
Models/QAHelperMapper.php
Normal file
74
Models/QAHelperMapper.php
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 8.0
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
||||
use phpOMS\DataStorage\Database\Query\Builder;
|
||||
|
||||
/**
|
||||
* Mapper class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class QAHelperMapper extends DataMapperAbstract
|
||||
{
|
||||
/**
|
||||
* Get total score of account
|
||||
*
|
||||
* @param array $accounts Accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAccountScore(array $accounts) : array
|
||||
{
|
||||
$scores = [];
|
||||
|
||||
$query = new Builder(self::$db);
|
||||
$questionScore = $query->select('qa_question_created_by')
|
||||
->selectAs('SUM(qa_question_vote_score)', 'score')
|
||||
->from(QAQuestionVoteMapper::getTable())
|
||||
->leftJoin(QAQuestionMapper::getTable())
|
||||
->on(QAQuestionVoteMapper::getTable() . '.qa_question_vote_question', '=', QAQuestionMapper::getTable() . '.qa_question_id')
|
||||
->where(QAQuestionMapper::getTable() . '.qa_question_created_by', 'in', $accounts)
|
||||
->groupBy('qa_question_created_by')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
|
||||
foreach ($questionScore as $votes) {
|
||||
$scores[(int) $votes['qa_question_created_by']] = (int) $votes['score'];
|
||||
}
|
||||
|
||||
$query = new Builder(self::$db);
|
||||
$answerScore = $query->select('qa_answer_created_by')
|
||||
->selectAs('SUM(qa_answer_vote_score)', 'score')
|
||||
->from(QAAnswerVoteMapper::getTable())
|
||||
->leftJoin(QAAnswerMapper::getTable())
|
||||
->on(QAAnswerVoteMapper::getTable() . '.qa_answer_vote_answer', '=', QAAnswerMapper::getTable() . '.qa_answer_id')
|
||||
->where(QAAnswerMapper::getTable() . '.qa_answer_created_by', 'in', $accounts)
|
||||
->groupBy('qa_answer_created_by')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
|
||||
foreach ($answerScore as $votes) {
|
||||
$scores[(int) $votes['qa_answer_created_by']] ??= 0;
|
||||
$scores[(int) $votes['qa_answer_created_by']] += (int) $votes['score'];
|
||||
}
|
||||
|
||||
return $scores;
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ use Modules\Profile\Models\Profile;
|
|||
use Modules\Tag\Models\Tag;
|
||||
|
||||
/**
|
||||
* Task class.
|
||||
* QA question class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
|
|
@ -68,14 +68,6 @@ class QAQuestion implements \JsonSerializable
|
|||
*/
|
||||
public string $questionRaw = '';
|
||||
|
||||
/**
|
||||
* Category.
|
||||
*
|
||||
* @var QACategory
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private ?QACategory $category = null;
|
||||
|
||||
/**
|
||||
* Language
|
||||
*
|
||||
|
|
@ -124,6 +116,12 @@ class QAQuestion implements \JsonSerializable
|
|||
*/
|
||||
private array $votes = [];
|
||||
|
||||
/**
|
||||
* App
|
||||
* @var int
|
||||
*/
|
||||
public QAApp $app;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
|
@ -133,6 +131,7 @@ class QAQuestion implements \JsonSerializable
|
|||
{
|
||||
$this->createdAt = new \DateTimeImmutable('now');
|
||||
$this->createdBy = new NullProfile();
|
||||
$this->app = new QAApp();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -147,6 +146,24 @@ class QAQuestion implements \JsonSerializable
|
|||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all accounts in Question
|
||||
* e.g. asked by and all accoounts who answered
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAccounts() : array
|
||||
{
|
||||
$accounts = [];
|
||||
$accounts[] = $this->createdBy->account->getId();
|
||||
|
||||
foreach ($this->answers as $answer) {
|
||||
$accounts[] = $answer->createdBy->account->getId();
|
||||
}
|
||||
|
||||
return \array_unique($accounts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the question have a accepted answer?
|
||||
*
|
||||
|
|
@ -157,7 +174,7 @@ class QAQuestion implements \JsonSerializable
|
|||
public function hasAccepted() : bool
|
||||
{
|
||||
foreach ($this->answers as $answer) {
|
||||
if ($answer->isAccepted()) {
|
||||
if ($answer->isAccepted) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -235,32 +252,6 @@ class QAQuestion implements \JsonSerializable
|
|||
$this->status = $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category
|
||||
*
|
||||
* @return QACategory
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getCategory() : QACategory
|
||||
{
|
||||
return $this->category ?? new NullQACategory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the category
|
||||
*
|
||||
* @param null|QACategory $category Category
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setCategory(?QACategory $category) : void
|
||||
{
|
||||
$this->category = $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags
|
||||
*
|
||||
|
|
@ -360,6 +351,34 @@ class QAQuestion implements \JsonSerializable
|
|||
return $this->answers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get answers by score
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getAnswersByScore() : array
|
||||
{
|
||||
$answers = $this->answers;
|
||||
\uasort($answers, [$this, 'sortByScore']);
|
||||
|
||||
return $answers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort by score
|
||||
*
|
||||
* @param QAAnswer $a1 Answer 1
|
||||
* @param QAAnswer $a2 Answer 2
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function sortByScore(QAAnswer $a1, QAAnswer $a2) : int
|
||||
{
|
||||
return $a2->getVoteScore() <=> $a1->getVoteScore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add answer to question
|
||||
*
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ final class QAQuestionMapper extends DataMapperAbstract
|
|||
'qa_question_question' => ['name' => 'qa_question_question', 'type' => 'string', 'internal' => 'question'],
|
||||
'qa_question_question_raw' => ['name' => 'qa_question_question_raw', 'type' => 'string', 'internal' => 'questionRaw'],
|
||||
'qa_question_status' => ['name' => 'qa_question_status', 'type' => 'int', 'internal' => 'status'],
|
||||
'qa_question_category' => ['name' => 'qa_question_category', 'type' => 'int', 'internal' => 'category'],
|
||||
'qa_question_created_by' => ['name' => 'qa_question_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],
|
||||
'qa_question_created_at' => ['name' => 'qa_question_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
||||
'qa_question_app' => ['name' => 'qa_question_app', 'type' => 'int', 'internal' => 'app'],
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -73,19 +73,6 @@ final class QAQuestionMapper extends DataMapperAbstract
|
|||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Has many relation.
|
||||
*
|
||||
* @var array<string, array<string, null|string>>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $ownsOne = [
|
||||
'category' => [
|
||||
'mapper' => QACategoryMapper::class,
|
||||
'external' => 'qa_question_category',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Belongs to.
|
||||
*
|
||||
|
|
@ -98,6 +85,10 @@ final class QAQuestionMapper extends DataMapperAbstract
|
|||
'external' => 'qa_question_created_by',
|
||||
'by' => 'account',
|
||||
],
|
||||
'app' => [
|
||||
'mapper' => QAAppMapper::class,
|
||||
'external' => 'qa_question_app',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
2
Models/QAQuestionVote.php
Normal file → Executable file
2
Models/QAQuestionVote.php
Normal file → Executable file
|
|
@ -18,7 +18,7 @@ use Modules\Admin\Models\Account;
|
|||
use Modules\Admin\Models\NullAccount;
|
||||
|
||||
/**
|
||||
* Task class.
|
||||
* QA question vote class.
|
||||
*
|
||||
* @package Modules\QA\Models
|
||||
* @license OMS License 1.0
|
||||
|
|
|
|||
4
Models/QAQuestionVoteMapper.php
Normal file → Executable file
4
Models/QAQuestionVoteMapper.php
Normal file → Executable file
|
|
@ -84,11 +84,11 @@ final class QAQuestionVoteMapper extends DataMapperAbstract
|
|||
* @param int $question Question id
|
||||
* @param int $account Account id
|
||||
*
|
||||
* @return QAQuestionVote
|
||||
* @return bool|QAQuestionVote
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function findVote(int $question, int $account) : QAQuestionVote
|
||||
public static function findVote(int $question, int $account) : bool|QAQuestionVote
|
||||
{
|
||||
$depth = 3;
|
||||
$query = self::getQuery();
|
||||
|
|
|
|||
|
|
@ -15,9 +15,25 @@ declare(strict_types=1);
|
|||
use Modules\Media\Models\NullMedia;
|
||||
use phpOMS\Uri\UriFactory;
|
||||
|
||||
/** @var \Modules\QA\Modles\QAQuestion[] $questions */
|
||||
$questions = $this->getData('questions');
|
||||
|
||||
/** @var \Modules\QA\Modles\QAApp[] $apps */
|
||||
$apps = $this->getData('apps');
|
||||
|
||||
echo $this->getData('nav')->render(); ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 box">
|
||||
<select>
|
||||
<option value="0"><?= $this->getHtml('All'); ?>
|
||||
<?php foreach ($apps as $app) : ?>
|
||||
<option value="<?= $app->getId(); ?>"><?= $app->name; ?>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<?php foreach ($questions as $question) : ?>
|
||||
|
|
|
|||
|
|
@ -15,11 +15,14 @@ declare(strict_types=1);
|
|||
use Modules\Media\Models\NullMedia;
|
||||
use phpOMS\Uri\UriFactory;
|
||||
|
||||
/** \Modules\QA\Models\QAQuestion $question */
|
||||
/** @var \Modules\QA\Models\QAQuestion $question */
|
||||
$question = $this->getData('question');
|
||||
|
||||
/** \Modules\QA\Models\QAAnswer[] $answers */
|
||||
$answers = $question->getAnswers();
|
||||
/** @var \Modules\QA\Models\QAAnswer[] $answers */
|
||||
$answers = $question->getAnswersByScore();
|
||||
|
||||
/** @var array $scores */
|
||||
$scores = $this->getData('scores');
|
||||
|
||||
echo $this->getData('nav')->render();
|
||||
?>
|
||||
|
|
@ -44,9 +47,7 @@ echo $this->getData('nav')->render();
|
|||
<section class="portlet">
|
||||
<div class="portlet-head"><?= $this->printHtml($question->name); ?></div>
|
||||
<div class="portlet-body">
|
||||
<article>
|
||||
<?= $question->question; ?>
|
||||
</article>
|
||||
<article><?= $question->question; ?></article>
|
||||
</div>
|
||||
<div class="portlet-foot qa-portlet-foot">
|
||||
<div class="tag-list">
|
||||
|
|
@ -56,7 +57,11 @@ echo $this->getData('nav')->render();
|
|||
</div>
|
||||
|
||||
<a class="account-info" href="<?= UriFactory::build('{/prefix}profile/single?{?}&id=' . $question->createdBy->getId()); ?>">
|
||||
<span class="name content"><?= $this->printHtml($question->createdBy->account->name2); ?>, <?= $this->printHtml($question->createdBy->account->name1); ?></span>
|
||||
<span class="name">
|
||||
<div class="content"><?= $this->printHtml($question->createdBy->account->name2); ?>, <?= $this->printHtml($question->createdBy->account->name1); ?></div>
|
||||
<div class="name-score">Score: <?= $scores[$question->createdBy->account->getId()] ?? 0 ?></div>
|
||||
</span>
|
||||
|
||||
<?php if ($question->createdBy->image !== null && !($question->createdBy->image instanceof NullMedia)) : ?>
|
||||
<img width="40px" alt="<?= $this->getHtml('AccountImage', '0', '0'); ?>" loading="lazy" src="<?= UriFactory::build('{/prefix}' . $question->createdBy->image->getPath()); ?>">
|
||||
<?php endif; ?>
|
||||
|
|
@ -93,7 +98,10 @@ echo $this->getData('nav')->render();
|
|||
</div>
|
||||
<div class="portlet-foot qa-portlet-foot">
|
||||
<a class="account-info" href="<?= UriFactory::build('{/prefix}profile/single?{?}&id=' . $answer->createdBy->getId()); ?>">
|
||||
<span class="name content"><?= $this->printHtml($answer->createdBy->account->name2); ?> <?= $this->printHtml($answer->createdBy->account->name1); ?></span>
|
||||
<span class="name">
|
||||
<div class="content"><?= $this->printHtml($answer->createdBy->account->name2); ?> <?= $this->printHtml($answer->createdBy->account->name1); ?></div>
|
||||
<div class="name-score">Score: <?= $scores[$answer->createdBy->account->getId()] ?? 0 ?></div>
|
||||
</span>
|
||||
<?php if ($answer->createdBy->image !== null && !($answer->createdBy->image instanceof NullMedia)) : ?>
|
||||
<img width="40px" alt="<?= $this->getHtml('AccountImage', '0', '0'); ?>" loading="lazy" src="<?= UriFactory::build('{/prefix}' . $answer->createdBy->image->getPath()); ?>">
|
||||
<?php endif; ?>
|
||||
|
|
|
|||
|
|
@ -62,4 +62,6 @@
|
|||
align-items: center;
|
||||
margin-left: auto; }
|
||||
.qa .qa-portlet-foot .account-info .name {
|
||||
margin-right: 10px; }
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
flex-direction: column; }
|
||||
|
|
|
|||
|
|
@ -108,6 +108,8 @@
|
|||
|
||||
.name {
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user