* strict type fixes
* news action added
This commit is contained in:
parent
22fe49d4ca
commit
6fa6c1ae89
@ -39,4 +39,6 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
|
||||
$app->get('/api/activity[/{id:\d+}]', App\Action\ActivityAction::class, 'api.activity.get');
|
||||
$app->get('/api/activity/signup/{id:\d+}', App\Action\ActivitySignupAction::class, 'api.activity.signup');
|
||||
$app->get('/api/activity/signoff/{id:\d+}', App\Action\ActivitySignoffAction::class, 'api.activity.signoff');
|
||||
|
||||
$app->get('/api/news[/{id:\d+}]', App\Action\NewsAction::class, 'api.news.get');
|
||||
};
|
||||
|
||||
@ -9,6 +9,8 @@ set('ssh_multiplexing', true);
|
||||
set('repository', 'ssh://gogs@gogs.ragnarok.yvan.hu:2206/yvan/skies-api.git');
|
||||
set('shared_dirs', [
|
||||
'data/tmp',
|
||||
'data/logs',
|
||||
'data/cache',
|
||||
]);
|
||||
set('shared_files', [
|
||||
// 'config/autoload/doctrine.local.php',
|
||||
@ -22,7 +24,7 @@ host('alfheim.ragnarok.yvan.hu')
|
||||
->stage('production')
|
||||
->user('yvan')
|
||||
->forwardAgent()
|
||||
->set('php_service_name', 'php7.1-fpm')
|
||||
->set('php_service_name', 'php7.2-fpm')
|
||||
->set('deploy_path', '/mnt/apps/skies-proxy-api');
|
||||
|
||||
desc('Restart PHP-FPM service');
|
||||
|
||||
@ -40,7 +40,7 @@ class ActivityAction extends AbstractAction
|
||||
*/
|
||||
public function get(ServerRequestInterface $request) : ResponseInterface
|
||||
{
|
||||
$id = $request->getAttribute(self::IDENTIFIER_NAME);
|
||||
$id = (int)$request->getAttribute(self::IDENTIFIER_NAME);
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->getActivity($id));
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ class ActivitySignoffAction implements RequestHandlerInterface
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request) : ResponseInterface
|
||||
{
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
$authHeader = (int)$request->getHeaderLine("x-passthru-auth");
|
||||
$id = $request->getAttribute("id");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->signOffActivity($id));
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ class ActivitySignupAction implements RequestHandlerInterface
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request) : ResponseInterface
|
||||
{
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
$authHeader = (int)$request->getHeaderLine("x-passthru-auth");
|
||||
$id = $request->getAttribute("id");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->signUpActivity($id));
|
||||
}
|
||||
|
||||
@ -3,8 +3,12 @@
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesClientService;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
|
||||
class NewsAction
|
||||
class NewsAction extends AbstractAction
|
||||
{
|
||||
/**
|
||||
* @var SkiesClientService
|
||||
@ -15,4 +19,27 @@ class NewsAction
|
||||
{
|
||||
$this->skiesClient = $skiesClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function getList(ServerRequestInterface $request) : ResponseInterface
|
||||
{
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->getNews());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function get(ServerRequestInterface $request) : ResponseInterface
|
||||
{
|
||||
$id = (int)$request->getAttribute(self::IDENTIFIER_NAME);
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->getNewsItem($id), 200, [], 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,211 @@
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
class News
|
||||
{
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
class News implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
private $date;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
private $finalEntry;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $accountable;
|
||||
|
||||
/**
|
||||
* @var ArrayCollection|Comment[]
|
||||
*/
|
||||
private $comments;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->comments = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return News
|
||||
*/
|
||||
public function setId(int $id): News
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return News
|
||||
*/
|
||||
public function setName(?string $name): News
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getDate(): ?\DateTime
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $date
|
||||
* @return News
|
||||
*/
|
||||
public function setDate(?\DateTime $date): News
|
||||
{
|
||||
$this->date = $date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
* @return News
|
||||
*/
|
||||
public function setDescription(?string $description): News
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getFinalEntry(): ?\DateTime
|
||||
{
|
||||
return $this->finalEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $finalEntry
|
||||
* @return News
|
||||
*/
|
||||
public function setFinalEntry(\DateTime $finalEntry): News
|
||||
{
|
||||
$this->finalEntry = $finalEntry;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAccountable(): ?string
|
||||
{
|
||||
return $this->accountable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accountable
|
||||
* @return News
|
||||
*/
|
||||
public function setAccountable(string $accountable): News
|
||||
{
|
||||
$this->accountable = $accountable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Comment[]|ArrayCollection
|
||||
*/
|
||||
public function getComments()
|
||||
{
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Comment[]|ArrayCollection $comments
|
||||
* @return News
|
||||
*/
|
||||
public function setComments($comments): News
|
||||
{
|
||||
$this->comments = $comments;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Comment $comment
|
||||
* @return News
|
||||
*/
|
||||
public function addComment(Comment $comment): News
|
||||
{
|
||||
if (!$this->comments->contains($comment)) {
|
||||
$this->comments->add($comment);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Comment $comment
|
||||
* @return News
|
||||
*/
|
||||
public function removeComment(Comment $comment): News
|
||||
{
|
||||
if ($this->comments->contains($comment)) {
|
||||
$this->comments->removeElement($comment);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'name' => $this->getName(),
|
||||
'date' => $this->getDate()
|
||||
? $this->getDate()->format("Y-m-d H:i:s")
|
||||
: null,
|
||||
'description' => $this->getDescription(),
|
||||
'accountable' => $this->getAccountable(),
|
||||
'comments' => $this->getComments()->getValues(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ namespace App\Service;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Comment;
|
||||
use App\Entity\News;
|
||||
use App\Entity\User;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Cookie\CookieJarInterface;
|
||||
@ -25,6 +26,7 @@ class SkiesClientService
|
||||
const SKIES_ACTIVITY_URL = "https://skies.sigmatechnology.se/main.asp?rID=2&alt=1&aktID=%s";
|
||||
const SKIES_ACTIVITY_SIGNUP_URL = "https://skies.sigmatechnology.se/main.asp?rID=2&alt=1&aktID=%s&doJoin=1";
|
||||
const SKIES_ACTIVITY_SIGNOFF_URL = "https://skies.sigmatechnology.se/main.asp?rID=2&alt=1&aktID=%s&doCancel=1&user=%s";
|
||||
const SKIES_NEWS_URL = "https://skies.sigmatechnology.se/main.asp?rID=200&coreID=%s";
|
||||
|
||||
/** @var Client */
|
||||
private $client;
|
||||
@ -90,13 +92,16 @@ class SkiesClientService
|
||||
*/
|
||||
public function setAuthHeader(string $authHeader): SkiesClientService
|
||||
{
|
||||
if ($authHeader == '') {
|
||||
throw new \InvalidArgumentException("Empty auth header", 500);
|
||||
}
|
||||
list($this->authUser, $this->authPass) = explode(':', base64_decode($authHeader));
|
||||
$this->cookieJar = new FileCookieJar("data/cache/".$this->authUser, true);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @return News[]
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function getNews()
|
||||
@ -389,9 +394,161 @@ class SkiesClientService
|
||||
return $formNodes->count() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $htmlBody
|
||||
* @return News[]
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
private function parseMainPage(string $htmlBody)
|
||||
{
|
||||
return false;
|
||||
$domDocument = new Document($htmlBody);
|
||||
$newsNodes = Document\Query::execute(
|
||||
"div.container div.row div.box div.one_block > a",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_CSS
|
||||
);
|
||||
|
||||
$news = [];
|
||||
for ($i = 1; $i < $newsNodes->count(); $i++) {
|
||||
$href = $newsNodes[$i]->attributes->getNamedItem("href")->textContent;
|
||||
$queryString = parse_url($href, PHP_URL_QUERY);
|
||||
parse_str($queryString, $queryParams);
|
||||
if ($queryParams['rID'] == 200 && isset($queryParams['coreID'])) {
|
||||
$news[] = $this->getNewsItem($queryParams["coreID"]);
|
||||
}
|
||||
}
|
||||
return $news;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return News
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function getNewsItem(int $id): News
|
||||
{
|
||||
$response = $this->doSkiesRequest('GET', sprintf(self::SKIES_NEWS_URL, $id));
|
||||
$htmlBody = $response->getBody();
|
||||
return $this->parseNewsPage($htmlBody, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $htmlBody
|
||||
* @param int $id
|
||||
* @return News
|
||||
*/
|
||||
private function parseNewsPage(string $htmlBody, int $id): News
|
||||
{
|
||||
$domDocument = new Document($htmlBody);
|
||||
/** News body */
|
||||
$activityNode = Document\Query::execute(
|
||||
"div.col-md-10 div.box",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_CSS
|
||||
);
|
||||
|
||||
/** News name */
|
||||
$h5Nodes = Document\Query::execute(
|
||||
"./h5",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$activityNode[0]
|
||||
);
|
||||
|
||||
/** Creator */
|
||||
$aNodes = Document\Query::execute(
|
||||
"./a",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$activityNode[0]
|
||||
);
|
||||
|
||||
$textNodes = Document\Query::execute(
|
||||
"./a/following::text()",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$activityNode[0]
|
||||
);
|
||||
preg_match("#\(Published: ([0-9]{4}-[0-9]{2}-[0-9]{2})\)#msi", $this->clearTextNode($textNodes[0]->textContent), $matches);
|
||||
|
||||
$contentDivNodes = Document\Query::execute(
|
||||
'.//div[@class="row"]/div[@class="col-md-12"]',
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$activityNode[0]
|
||||
);
|
||||
|
||||
/** Comment block */
|
||||
$commentNodes = Document\Query::execute(
|
||||
'.//div[@class="onecomment"]',
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$activityNode[0]
|
||||
);
|
||||
|
||||
$news = new News();
|
||||
$news->setId($id)
|
||||
->setName($this->clearTextNode($h5Nodes[0]->textContent))
|
||||
->setDescription($this->parseNewsDescription($contentDivNodes[0]))
|
||||
->setDate(isset($matches[1]) ? new \DateTime($matches[1]) : null)
|
||||
->setAccountable($this->clearTextNode($aNodes[0]->textContent));
|
||||
// $this->parseNewsComments($commentNodes, $news);
|
||||
|
||||
return $news;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DOMNode $element
|
||||
* @return null|string
|
||||
*/
|
||||
private function parseNewsDescription(\DOMNode $element): ?string
|
||||
{
|
||||
$description = "";
|
||||
/** @var \DOMElement $childNode */
|
||||
foreach ($element->childNodes as $childNode) {
|
||||
$description .= $childNode->nodeName == "br"
|
||||
? "\n"
|
||||
: rtrim($childNode->textContent);
|
||||
}
|
||||
return $this->clearTextNode($description);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document\NodeList $commentElements
|
||||
* @param News $news
|
||||
*/
|
||||
private function parseNewsComments(Document\NodeList $commentElements, News $news)
|
||||
{
|
||||
/** @var \DOMElement $commentElement */
|
||||
foreach ($commentElements as $commentElement) {
|
||||
$divElements = $commentElement->getElementsByTagName("div");
|
||||
|
||||
$queryString = parse_url(
|
||||
$commentElement->getElementsByTagName("a")->item(0)->getAttribute("href"),
|
||||
PHP_URL_QUERY
|
||||
);
|
||||
parse_str($queryString, $queryParams);
|
||||
preg_match(
|
||||
"#(.*)\s/\s([0-9]{4}-[0-9]{2}-[0-9]{2})\s([0-9]{1,2}:[0-9]{1,2})#msi",
|
||||
str_replace(" ", " ", $divElements->item(2)->textContent),
|
||||
$matches
|
||||
);
|
||||
|
||||
$user = new User();
|
||||
$user->setDisplayName($matches[1])
|
||||
->setUsername($queryParams['username']);
|
||||
|
||||
$comment = new Comment();
|
||||
$comment
|
||||
->setText($divElements->item(1)->textContent)
|
||||
->setUser($user)
|
||||
->setCreatedAt(new \DateTime(sprintf(
|
||||
"%s %s",
|
||||
$matches[2],
|
||||
$matches[3]
|
||||
)));
|
||||
$news->addComment($comment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -421,10 +578,13 @@ class SkiesClientService
|
||||
*/
|
||||
private function clearTextNode(string $text): string
|
||||
{
|
||||
$text = str_replace("\r", "", $text);
|
||||
$text = str_replace(" ", " ", $text);
|
||||
$text = str_replace("", "-", $text);
|
||||
// $text = str_replace(chr(0xC2).chr(0x95), "-", $text);
|
||||
$text = str_replace([chr(0xC2).chr(0x93), chr(0xC2).chr(0x94)], '"', $text);
|
||||
$text = preg_replace("#[ \t]+#msiu", " ", $text);
|
||||
return trim($text, " \t\n\r\0\x0B" . chr(0xC2) . chr(0xA0));
|
||||
return trim($text, " \t\n\r\0\x0B " . chr(0xC2) . chr(0xA0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user