draft demo

This commit is contained in:
Dennis Eichhorn 2020-11-22 00:01:31 +01:00
parent 00d4e1cde3
commit a440a1b5c0
11 changed files with 505 additions and 53 deletions

View File

@ -9,11 +9,6 @@
"primary": true,
"autoincrement": true
},
"qa_category_name": {
"name": "qa_category_name",
"type": "VARCHAR(255)",
"null": false
},
"qa_category_parent": {
"name": "qa_category_parent",
"type": "INT",
@ -24,6 +19,38 @@
}
}
},
"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",
"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"
}
}
},
"qa_question": {
"name": "qa_question",
"fields": {
@ -77,6 +104,32 @@
}
}
},
"qa_tag": {
"name": "qa_tag",
"fields": {
"qa_tag_id": {
"name": "qa_tag_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"qa_tag_dst": {
"name": "qa_tag_dst",
"type": "INT",
"null": false,
"foreignTable": "qa_question",
"foreignKey": "qa_question_id"
},
"qa_tag_src": {
"name": "qa_tag_src",
"type": "INT",
"null": false,
"foreignTable": "tag",
"foreignKey": "tag_id"
}
}
},
"qa_answer": {
"name": "qa_answer",
"fields": {

View File

@ -29,6 +29,13 @@ use phpOMS\Message\RequestAbstract;
use phpOMS\Message\ResponseAbstract;
use phpOMS\Model\Message\FormValidation;
use phpOMS\Utils\Parser\Markdown\Markdown;
use phpOMS\Message\Http\HttpRequest;
use phpOMS\Message\NotificationLevel;
use Modules\QA\Models\QACategoryL11n;
use Modules\Tag\Models\NullTag;
use phpOMS\Message\Http\HttpResponse;
use Modules\Admin\Models\NullAccount;
use Modules\QA\Models\QACategoryL11nMapper;
/**
* Task class.
@ -69,21 +76,23 @@ final class ApiController extends Controller
return;
}
$question = $this->createQAQuestionFromRquest($request);
QAQuestionMapper::create($question);
$response->set('question', $question->jsonSerialize());
$question = $this->createQAQuestionFromRequest($request, $response, $data);
$this->createModel($request->getHeader()->getAccount(), $question, QAQuestionMapper::class, 'question', $request->getOrigin());
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Question', 'Question successfully created.', $question);
}
/**
* Method to create question from request.
*
* @param RequestAbstract $request Request
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param mixed $data Generic data
*
* @return QAQuestion Returns the created question from the request
*
* @since 1.0.0
*/
public function createQAQuestionFromRquest(RequestAbstract $request) : QAQuestion
public function createQAQuestionFromRequest(RequestAbstract $request, ResponseAbstract $response, $data = null) : QAQuestion
{
$mardkownParser = new Markdown();
@ -93,7 +102,23 @@ final class ApiController extends Controller
$question->setLanguage((string) $request->getData('language'));
$question->setCategory(new NullQACategory((int) $request->getData('category')));
$question->setStatus((int) $request->getData('status'));
$question->setBadges((array) $request->getData('badges'));
$question->setCreatedBy(new NullAccount($request->getHeader()->getAccount()));
if (!empty($tags = $request->getDataJson('tags'))) {
foreach ($tags as $tag) {
if (!isset($tag['id'])) {
$request->setData('title', $tag['title'], true);
$request->setData('color', $tag['color'], true);
$request->setData('language', $tag['language'], true);
$internalResponse = new HttpResponse();
$this->app->moduleManager->get('Tag')->apiTagCreate($request, $internalResponse, $data);
$question->addTag($internalResponse->get($request->getUri()->__toString())['response']);
} else {
$question->addTag(new NullTag((int) $tag['id']));
}
}
}
return $question;
}
@ -114,7 +139,6 @@ final class ApiController extends Controller
|| ($val['plain'] = empty($request->getData('plain')))
|| ($val['language'] = empty($request->getData('language')))
|| ($val['category'] = empty($request->getData('category')))
|| ($val['badges'] = empty($request->getData('badges')))
|| ($val['status'] = (
$request->getData('status') !== null
&& !QAQuestionStatus::isValidValue((int) $request->getData('status'))
@ -148,9 +172,9 @@ final class ApiController extends Controller
return;
}
$answer = $this->createQAAnswerFromRquest($request);
QAAnswerMapper::create($answer);
$response->set('answer', $answer->jsonSerialize());
$answer = $this->createQAAnswerFromRequest($request);
$this->createModel($request->getHeader()->getAccount(), $answer, QAAnswerMapper::class, 'answer', $request->getOrigin());
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Answer', 'Answer successfully created.', $answer);
}
/**
@ -162,7 +186,7 @@ final class ApiController extends Controller
*
* @since 1.0.0
*/
public function createQAAnswerFromRquest(RequestAbstract $request) : QAAnswer
public function createQAAnswerFromRequest(RequestAbstract $request) : QAAnswer
{
$mardkownParser = new Markdown();
@ -170,6 +194,7 @@ final class ApiController extends Controller
$answer->setAnswer((string) $request->getData('plain'));
$answer->setQuestion(new NullQAQuestion((int) $request->getData('question')));
$answer->setStatus((int) $request->getData('status'));
$answer->setCreatedBy(new NullAccount($request->getHeader()->getAccount()));
return $answer;
}
@ -186,8 +211,7 @@ final class ApiController extends Controller
private function validateQAAnswerCreate(RequestAbstract $request) : array
{
$val = [];
if (($val['title'] = empty($request->getData('title')))
|| ($val['plain'] = empty($request->getData('plain')))
if (($val['plain'] = empty($request->getData('plain')))
|| ($val['question'] = empty($request->getData('question')))
|| ($val['status'] = (
$request->getData('status') !== null
@ -222,9 +246,20 @@ final class ApiController extends Controller
return;
}
$category = $this->createQACategoryFromRquest($request);
QACategoryMapper::create($category);
$response->set('category', $category->jsonSerialize());
$category = $this->createQACategoryFromRequest($request);
$this->createModel($request->getHeader()->getAccount(), $category, QACategoryMapper::class, 'category', $request->getOrigin());
$l11nRequest = new HttpRequest($request->getUri());
$l11nRequest->setData('category', $category->getId());
$l11nRequest->setData('name', $request->getData('name'));
$l11nRequest->setData('language', $request->getData('language'));
$l11nQACategory = $this->createQACategoryL11nFromRequest($l11nRequest);
$this->createModel($request->getHeader()->getAccount(), $l11nQACategory, QACategoryL11nMapper::class, 'tag_l11n', $request->getOrigin());
$category->setName($l11nQACategory);
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Category', 'Category successfully created.', $category);
}
/**
@ -236,13 +271,14 @@ final class ApiController extends Controller
*
* @since 1.0.0
*/
public function createQACategoryFromRquest(RequestAbstract $request) : QACategory
public function createQACategoryFromRequest(RequestAbstract $request) : QACategory
{
$mardkownParser = new Markdown();
$category = new QACategory();
$category->setName((string) $request->getData('title'));
$category->setParent($request->getData('parent') === null ? null : new NullQACategory((int) $request->getData('parent')));
//$category->setApp(new NullQAApp((int) ($request->getData('app') ?? 1)));
if ($request->getData('parent') !== null) {
$category->setParent(new NullQACategory((int) $request->getData('parent')));
}
return $category;
}
@ -259,12 +295,80 @@ final class ApiController extends Controller
private function validateQACategoryCreate(RequestAbstract $request) : array
{
$val = [];
if (($val['title'] = empty($request->getData('title')))
|| ($val['parent'] = empty($request->getData('parent')))
if (($val['name'] = empty($request->getData('name')))) {
return $val;
}
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->getHeader()->setStatusCode(RequestStatusCode::R_400);
return;
}
$l11nQACategory = $this->createQACategoryL11nFromRequest($request);
$this->createModel($request->getHeader()->getAccount(), $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->setName((string) ($request->getData('name') ?? ''));
return $l11nQACategory;
}
}

View File

@ -71,7 +71,7 @@ final class BackendController extends Controller
$view->setTemplate('/Modules/QA/Theme/Backend/qa-dashboard');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1006001001, $request, $response));
$list = QAQuestionMapper::getNewest(50);
$list = QAQuestionMapper::withConditional('language', $response->getLanguage())::getNewest(50);
$view->setData('questions', $list);
return $view;

View File

@ -14,6 +14,8 @@ declare(strict_types=1);
namespace Modules\QA\Models;
use phpOMS\Localization\ISO639x1Enum;
/**
* Task class.
*
@ -35,10 +37,10 @@ class QACategory implements \JsonSerializable
/**
* Name.
*
* @var string
* @var string|QACategoryL11n
* @since 1.0.0
*/
private string $name = '';
private $name = '';
/**
* Parent category.
@ -69,21 +71,29 @@ class QACategory implements \JsonSerializable
*/
public function getName() : string
{
return $this->name;
return $this->name instanceof QACategoryL11n ? $this->name->getName() : $this->name;
}
/**
* Set name
*
* @param string $name Name
* @param string|TagL11n $name Tag article name
*
* @return void
*
* @since 1.0.0
*/
public function setName(string $name) : void
public function setName($name, string $lang = ISO639x1Enum::_EN) : void
{
$this->name = $name;
if ($name instanceof QACategoryL11n) {
$this->name = $name;
} elseif ($this->name instanceof QACategoryL11n && \is_string($name)) {
$this->name->setName($name);
} elseif (\is_string($name)) {
$this->name = new QACategoryL11n();
$this->name->setName($name);
$this->name->setLanguage($lang);
}
}
/**

185
Models/QACategoryL11n.php Normal file
View File

@ -0,0 +1,185 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @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
*/
private 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;
}
/**
* Set name
*
* @param string $name Name
*
* @return void
*
* @since 1.0.0
*/
public function setName(string $name) : void
{
$this->name = $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();
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @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\Localization\Defaults\LanguageMapper;
/**
* Category mapper class.
*
* @package Modules\QA\Models
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*
* @todo Do I really want to create a relation to the language mapper? It's not really needed right?
*/
final class QACategoryL11nMapper 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_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'],
];
/**
* Has one relation.
*
* @var array<string, array{mapper:string, external:string, by?:string, column?:string, conditional?:bool}>
* @since 1.0.0
*/
protected static array $ownsOne = [
'language' => [
'mapper' => LanguageMapper::class,
'external' => 'qa_category_l11n_language',
'by' => 'code2',
'column' => 'code2',
'conditional' => true,
],
];
/**
* Primary table.
*
* @var string
* @since 1.0.0
*/
protected static string $table = 'qa_category_l11n';
/**
* Primary field name.
*
* @var string
* @since 1.0.0
*/
protected static string $primaryField = 'qa_category_l11n_id';
}

View File

@ -34,7 +34,6 @@ final class QACategoryMapper extends DataMapperAbstract
*/
protected static array $columns = [
'qa_category_id' => ['name' => 'qa_category_id', 'type' => 'int', 'internal' => 'id'],
'qa_category_name' => ['name' => 'qa_category_name', 'type' => 'string', 'internal' => 'name'],
'qa_category_parent' => ['name' => 'qa_category_parent', 'type' => 'int', 'internal' => 'parent'],
];
@ -51,6 +50,23 @@ final class QACategoryMapper extends DataMapperAbstract
],
];
/**
* 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.
*

View File

@ -93,12 +93,12 @@ class QAQuestion implements \JsonSerializable
private \DateTimeImmutable $createdAt;
/**
* Badges.
* Tags.
*
* @var array<int, int|Tag>
* @since 1.0.0
*/
private array $badges = [];
private array $tags = [];
/**
* Answers.
@ -336,35 +336,35 @@ class QAQuestion implements \JsonSerializable
}
/**
* Get badges
* Get tags
*
* @return array
*
* @since 1.0.0
*/
public function getBadges() : array
public function getTags() : array
{
return $this->badges;
return $this->tags;
}
/**
* Add badge to question
* Add tag to question
*
* @param int|Tag $badge Badge
* @param int|Tag $tag Tag
*/
public function addBadge($badge) : void
public function addTag($tag) : void
{
$this->badges[] = $badge;
$this->tags[] = $tag;
}
/**
* Set badges to question
* Set tags to question
*
* @param array<int, int|Tag> $badges Badges
* @param array<int, int|Tag> $tags Tags
*/
public function setBadges(array $badges) : void
public function setTags(array $tags) : void
{
$this->badges = $badges;
$this->tags = $tags;
}
/**

View File

@ -16,6 +16,7 @@ namespace Modules\QA\Models;
use Modules\Admin\Models\AccountMapper;
use phpOMS\DataStorage\Database\DataMapperAbstract;
use Modules\Tag\Models\TagMapper;
/**
* Mapper class.
@ -57,6 +58,12 @@ final class QAQuestionMapper extends DataMapperAbstract
'self' => 'qa_answer_question',
'external' => null,
],
'tags' => [
'mapper' => TagMapper::class,
'table' => 'qa_tag',
'self' => 'qa_tag_dst',
'external' => 'qa_tag_src',
],
];
/**

View File

@ -18,8 +18,8 @@ echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12">
<?php foreach ($questions as $question) : ?>
<section class="box wf-100 qa-list">
<div class="inner">
<section class="portlet qa-list">
<div class="portlet-body">
<div class="row middle-xs">
<div class="col-xs-1 scores">
<span class="score<?= $this->printHtml($question->hasAccepted() ? ' done' : ''); ?>"><?= $this->printHtml(\count($question->getAnswers())); ?></span>
@ -29,8 +29,8 @@ echo $this->getData('nav')->render(); ?>
</div>
</div>
<div class="tags">
<?php $badges = $question->getBadges(); foreach ($badges as $badge) : ?>
<span class="tag red"><?= $this->printHtml($badge->getName()); ?></span>
<?php $tags = $question->getTags(); foreach ($tags as $tag) : ?>
<span class="tag red"><?= $this->printHtml($tag->getTitle()); ?></span>
<?php endforeach; ?>
</div>
</div>

View File

@ -17,6 +17,7 @@
"description": "QA module.",
"directory": "QA",
"dependencies": {
"Tag": "1.0.0",
"Admin": "1.0.0",
"Editor": "1.0.0",
"Tools": "1.0.0"