* uplift to latest expressive
This commit is contained in:
@@ -2,16 +2,17 @@
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
use Zend\Json\Json;
|
||||
|
||||
abstract class AbstractAction implements MiddlewareInterface
|
||||
abstract class AbstractAction implements ServerMiddlewareInterface
|
||||
{
|
||||
const IDENTIFIER_NAME = 'id';
|
||||
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
$requestMethod = strtoupper($request->getMethod());
|
||||
$id = $request->getAttribute(static::IDENTIFIER_NAME);
|
||||
@@ -19,68 +20,68 @@ abstract class AbstractAction implements MiddlewareInterface
|
||||
switch ($requestMethod) {
|
||||
case 'GET':
|
||||
return isset($id)
|
||||
? $this->get($request, $response, $next)
|
||||
: $this->getList($request, $response, $next);
|
||||
? $this->get($request, $delegate)
|
||||
: $this->getList($request, $delegate);
|
||||
case 'POST':
|
||||
return $this->create($request, $response, $next);
|
||||
return $this->create($request, $delegate);
|
||||
case 'PUT':
|
||||
return $this->update($request, $response, $next);
|
||||
return $this->update($request, $delegate);
|
||||
case 'DELETE':
|
||||
return isset($id)
|
||||
? $this->delete($request, $response, $next)
|
||||
: $this->deleteList($request, $response, $next);
|
||||
? $this->delete($request, $delegate)
|
||||
: $this->deleteList($request, $delegate);
|
||||
case 'HEAD':
|
||||
return $this->head($request, $response, $next);
|
||||
return $this->head($request, $delegate);
|
||||
case 'OPTIONS':
|
||||
return $this->options($request, $response, $next);
|
||||
return $this->options($request, $delegate);
|
||||
case 'PATCH':
|
||||
return $this->patch($request, $response, $next);
|
||||
return $this->patch($request, $delegate);
|
||||
default:
|
||||
return $next($request, $response);
|
||||
return $delegate->process($request);
|
||||
}
|
||||
}
|
||||
|
||||
public function get(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function get(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
public function getList(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function getList(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
public function create(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function create(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
public function update(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function update(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
public function delete(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function delete(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
public function deleteList(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function deleteList(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
public function head(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function head(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
public function options(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function options(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
public function patch(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function patch(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||
}
|
||||
@@ -89,4 +90,69 @@ abstract class AbstractAction implements MiddlewareInterface
|
||||
{
|
||||
return new JsonResponse($data, $status);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @return array|object
|
||||
*/
|
||||
public function getRequestData(ServerRequestInterface $request)
|
||||
{
|
||||
$body = $request->getParsedBody();
|
||||
|
||||
if (!empty($body)) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
return $this->parseRequestData(
|
||||
$request->getBody()->getContents(),
|
||||
$request->getHeaderLine('content-type')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $input
|
||||
* @param string $contentType
|
||||
* @return mixed
|
||||
*/
|
||||
private function parseRequestData($input, $contentType)
|
||||
{
|
||||
$contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType);
|
||||
$parser = $this->returnParserContentType($contentTypeParts[0]);
|
||||
|
||||
return $parser($input);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $contentType
|
||||
* @return callable
|
||||
*/
|
||||
private function returnParserContentType(string $contentType)
|
||||
{
|
||||
if ($contentType === 'application/x-www-form-urlencoded') {
|
||||
return function ($input) {
|
||||
parse_str($input, $data);
|
||||
return $data;
|
||||
};
|
||||
} elseif ($contentType === 'application/json') {
|
||||
return function ($input) {
|
||||
$jsonDecoder = new Json();
|
||||
try {
|
||||
return $jsonDecoder->decode($input, Json::TYPE_ARRAY);
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} elseif ($contentType === 'multipart/form-data') {
|
||||
return function ($input) {
|
||||
return $input;
|
||||
};
|
||||
}
|
||||
|
||||
return function ($input) {
|
||||
return $input;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,33 +2,34 @@
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesService;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use App\Service\SkiesClientService;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
use Zend\Diactoros\Response\TextResponse;
|
||||
|
||||
class ActivityAction extends AbstractAction
|
||||
{
|
||||
private $skiesService;
|
||||
/**
|
||||
* @var SkiesClientService
|
||||
*/
|
||||
private $skiesClient;
|
||||
|
||||
public function __construct(SkiesService $skiesService)
|
||||
public function __construct(SkiesClientService $skiesClient)
|
||||
{
|
||||
$this->skiesService = $skiesService;
|
||||
$this->skiesClient = $skiesClient;
|
||||
}
|
||||
|
||||
public function getList(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function getList(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return new JsonResponse($this->skiesService->getActivityList());
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->getActivities());
|
||||
}
|
||||
|
||||
public function get(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function get(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
$id = $request->getAttribute(self::IDENTIFIER_NAME);
|
||||
return new JsonResponse($this->skiesService->getActivity($id));
|
||||
}
|
||||
|
||||
public function options(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
{
|
||||
return new JsonResponse(true);
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->getActivity($id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesService;
|
||||
use App\Service\SkiesClientService;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class ActivityFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$skiesService = $container->get(SkiesService::class);
|
||||
return new ActivityAction($skiesService);
|
||||
$skiesClient = $container->get(SkiesClientService::class);
|
||||
return new ActivityAction($skiesClient);
|
||||
}
|
||||
}
|
||||
|
||||
29
src/App/Action/ActivitySignoffAction.php
Normal file
29
src/App/Action/ActivitySignoffAction.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesClientService;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
|
||||
class ActivitySignoffAction implements ServerMiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* @var SkiesClientService
|
||||
*/
|
||||
private $skiesClient;
|
||||
|
||||
public function __construct(SkiesClientService $skiesClient)
|
||||
{
|
||||
$this->skiesClient = $skiesClient;
|
||||
}
|
||||
|
||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
$id = $request->getAttribute("id");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->signOffActivity($id));
|
||||
}
|
||||
}
|
||||
15
src/App/Action/ActivitySignoffFactory.php
Normal file
15
src/App/Action/ActivitySignoffFactory.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesClientService;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class ActivitySignoffFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$skiesClient = $container->get(SkiesClientService::class);
|
||||
return new ActivitySignoffAction($skiesClient);
|
||||
}
|
||||
}
|
||||
29
src/App/Action/ActivitySignupAction.php
Normal file
29
src/App/Action/ActivitySignupAction.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesClientService;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
|
||||
class ActivitySignupAction implements ServerMiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* @var SkiesClientService
|
||||
*/
|
||||
private $skiesClient;
|
||||
|
||||
public function __construct(SkiesClientService $skiesClient)
|
||||
{
|
||||
$this->skiesClient = $skiesClient;
|
||||
}
|
||||
|
||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
$authHeader = $request->getHeaderLine("x-passthru-auth");
|
||||
$id = $request->getAttribute("id");
|
||||
return new JsonResponse($this->skiesClient->setAuthHeader($authHeader)->signUpActivity($id));
|
||||
}
|
||||
}
|
||||
15
src/App/Action/ActivitySignupFactory.php
Normal file
15
src/App/Action/ActivitySignupFactory.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesClientService;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class ActivitySignupFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$skiesClient = $container->get(SkiesClientService::class);
|
||||
return new ActivitySignupAction($skiesClient);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Zend\Diactoros\Response\HtmlResponse;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
@@ -12,7 +13,7 @@ use Zend\Expressive\Plates\PlatesRenderer;
|
||||
use Zend\Expressive\Twig\TwigRenderer;
|
||||
use Zend\Expressive\ZendView\ZendViewRenderer;
|
||||
|
||||
class HomePageAction
|
||||
class HomePageAction implements ServerMiddlewareInterface
|
||||
{
|
||||
private $router;
|
||||
|
||||
@@ -24,8 +25,15 @@ class HomePageAction
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
if (! $this->template) {
|
||||
return new JsonResponse([
|
||||
'welcome' => 'Congratulations! You have installed the zend-expressive skeleton application.',
|
||||
'docsUrl' => 'https://docs.zendframework.com/zend-expressive/',
|
||||
]);
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
if ($this->router instanceof Router\AuraRouter) {
|
||||
@@ -36,7 +44,7 @@ class HomePageAction
|
||||
$data['routerDocs'] = 'https://github.com/nikic/FastRoute';
|
||||
} elseif ($this->router instanceof Router\ZendRouter) {
|
||||
$data['routerName'] = 'Zend Router';
|
||||
$data['routerDocs'] = 'http://framework.zend.com/manual/current/en/modules/zend.mvc.routing.html';
|
||||
$data['routerDocs'] = 'https://docs.zendframework.com/zend-router/';
|
||||
}
|
||||
|
||||
if ($this->template instanceof PlatesRenderer) {
|
||||
@@ -47,14 +55,7 @@ class HomePageAction
|
||||
$data['templateDocs'] = 'http://twig.sensiolabs.org/documentation';
|
||||
} elseif ($this->template instanceof ZendViewRenderer) {
|
||||
$data['templateName'] = 'Zend View';
|
||||
$data['templateDocs'] = 'http://framework.zend.com/manual/current/en/modules/zend.view.quick-start.html';
|
||||
}
|
||||
|
||||
if (!$this->template) {
|
||||
return new JsonResponse([
|
||||
'welcome' => 'Congratulations! You have installed the zend-expressive skeleton application.',
|
||||
'docsUrl' => 'zend-expressive.readthedocs.org',
|
||||
]);
|
||||
$data['templateDocs'] = 'https://docs.zendframework.com/zend-view/';
|
||||
}
|
||||
|
||||
return new HtmlResponse($this->template->render('app::home-page', $data));
|
||||
|
||||
@@ -11,7 +11,7 @@ class HomePageFactory
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$router = $container->get(RouterInterface::class);
|
||||
$template = ($container->has(TemplateRendererInterface::class))
|
||||
$template = $container->has(TemplateRendererInterface::class)
|
||||
? $container->get(TemplateRendererInterface::class)
|
||||
: null;
|
||||
|
||||
|
||||
18
src/App/Action/NewsAction.php
Normal file
18
src/App/Action/NewsAction.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesClientService;
|
||||
|
||||
class NewsAction
|
||||
{
|
||||
/**
|
||||
* @var SkiesClientService
|
||||
*/
|
||||
private $skiesClient;
|
||||
|
||||
public function __construct(SkiesClientService $skiesClient)
|
||||
{
|
||||
$this->skiesClient = $skiesClient;
|
||||
}
|
||||
}
|
||||
15
src/App/Action/NewsFactory.php
Normal file
15
src/App/Action/NewsFactory.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\SkiesClientService;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class NewsFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$skiesClient = $container->get(SkiesClientService::class);
|
||||
return new NewsAction($skiesClient);
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,15 @@
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class PingAction
|
||||
class PingAction implements ServerMiddlewareInterface
|
||||
{
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
return new JsonResponse([
|
||||
'ack' => time(),
|
||||
]);
|
||||
return new JsonResponse(['ack' => time()]);
|
||||
}
|
||||
}
|
||||
|
||||
66
src/App/ConfigProvider.php
Normal file
66
src/App/ConfigProvider.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
/**
|
||||
* The configuration provider for the App module
|
||||
*
|
||||
* @see https://docs.zendframework.com/zend-component-installer/
|
||||
*/
|
||||
class ConfigProvider
|
||||
{
|
||||
/**
|
||||
* Returns the configuration array
|
||||
*
|
||||
* To add a bit of a structure, each section is defined in a separate
|
||||
* method which returns an array with its configuration.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
return [
|
||||
'dependencies' => $this->getDependencies(),
|
||||
'templates' => $this->getTemplates(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the container dependencies
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDependencies()
|
||||
{
|
||||
return [
|
||||
'invokables' => [
|
||||
Action\PingAction::class => Action\PingAction::class,
|
||||
],
|
||||
'factories' => [
|
||||
Action\HomePageAction::class => Action\HomePageFactory::class,
|
||||
Action\ActivityAction::class => Action\ActivityFactory::class,
|
||||
Action\ActivitySignupAction::class => Action\ActivitySignupFactory::class,
|
||||
Action\ActivitySignoffAction::class => Action\ActivitySignoffFactory::class,
|
||||
Action\NewsAction::class => Action\NewsFactory::class,
|
||||
|
||||
Service\SkiesClientService::class => Service\SkiesClientServiceFactory::class,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the templates configuration
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplates()
|
||||
{
|
||||
return [
|
||||
'paths' => [
|
||||
'app' => ['templates/app'],
|
||||
'error' => ['templates/error'],
|
||||
'layout' => ['templates/layout'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
305
src/App/Entity/Activity.php
Normal file
305
src/App/Entity/Activity.php
Normal file
@@ -0,0 +1,305 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
class Activity 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;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $signedUsers;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isSignedup = false;
|
||||
|
||||
/**
|
||||
* Can sign up or sign off activity
|
||||
* @var bool
|
||||
*/
|
||||
private $canChangeSignup = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->comments = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Activity
|
||||
*/
|
||||
public function setId(int $id)
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return Activity
|
||||
*/
|
||||
public function setName(?string $name): Activity
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getDate(): ?\DateTime
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $date
|
||||
* @return Activity
|
||||
*/
|
||||
public function setDate(?\DateTime $date): Activity
|
||||
{
|
||||
$this->date = $date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
* @return Activity
|
||||
*/
|
||||
public function setDescription(?string $description): Activity
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getFinalEntry(): ?\DateTime
|
||||
{
|
||||
return $this->finalEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $finalEntry
|
||||
* @return Activity
|
||||
*/
|
||||
public function setFinalEntry(\DateTime $finalEntry): Activity
|
||||
{
|
||||
$this->finalEntry = $finalEntry;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAccountable(): ?string
|
||||
{
|
||||
return $this->accountable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accountable
|
||||
* @return Activity
|
||||
*/
|
||||
public function setAccountable(string $accountable): Activity
|
||||
{
|
||||
$this->accountable = $accountable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Comment[]|ArrayCollection
|
||||
*/
|
||||
public function getComments()
|
||||
{
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Comment[]|ArrayCollection $comments
|
||||
* @return Activity
|
||||
*/
|
||||
public function setComments($comments): Activity
|
||||
{
|
||||
$this->comments = $comments;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Comment $comment
|
||||
* @return Activity
|
||||
*/
|
||||
public function addComment(Comment $comment): Activity
|
||||
{
|
||||
if(!$this->comments->contains($comment)) {
|
||||
$this->comments->add($comment);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Comment $comment
|
||||
* @return Activity
|
||||
*/
|
||||
public function removeComment(Comment $comment): Activity
|
||||
{
|
||||
if($this->comments->contains($comment)) {
|
||||
$this->comments->removeElement($comment);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getSignedUsers(): ?array
|
||||
{
|
||||
return $this->signedUsers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $signedUsers
|
||||
* @return Activity
|
||||
*/
|
||||
public function setSignedUsers(array $signedUsers): Activity
|
||||
{
|
||||
$this->signedUsers = $signedUsers;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $signed
|
||||
* @return Activity
|
||||
*/
|
||||
public function addSignedUser(string $signed): Activity
|
||||
{
|
||||
$this->signedUsers[] = $signed;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSignedup(): bool
|
||||
{
|
||||
return $this->isSignedup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isSignedup
|
||||
* @return Activity
|
||||
*/
|
||||
public function setIsSignedup(bool $isSignedup): Activity
|
||||
{
|
||||
$this->isSignedup = $isSignedup;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isCanChangeSignup(): bool
|
||||
{
|
||||
return $this->canChangeSignup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $canChangeSignup
|
||||
* @return Activity
|
||||
*/
|
||||
public function setCanChangeSignup(bool $canChangeSignup): Activity
|
||||
{
|
||||
$this->canChangeSignup = $canChangeSignup;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify data which should be serialized to JSON
|
||||
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
* @return mixed data which can be serialized by <b>json_encode</b>,
|
||||
* which is a value of any type other than a resource.
|
||||
* @since 5.4.0
|
||||
*/
|
||||
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(),
|
||||
'finalEntry' => $this->getFinalEntry()
|
||||
? $this->getFinalEntry()->format("Y-m-d H:i:s")
|
||||
: null,
|
||||
'accountable' => $this->getAccountable(),
|
||||
'comments' => $this->getComments()->getValues(),
|
||||
'signedUsers' => $this->getSignedUsers(),
|
||||
'canChangeSignup' => $this->isCanChangeSignup(),
|
||||
'isSignedUp' => $this->isSignedup()
|
||||
];
|
||||
}
|
||||
}
|
||||
93
src/App/Entity/Comment.php
Normal file
93
src/App/Entity/Comment.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
class Comment implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
private $createdAt;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getText(): string
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @return Comment
|
||||
*/
|
||||
public function setText(string $text): Comment
|
||||
{
|
||||
$this->text = $text;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getCreatedAt(): \DateTime
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $createdAt
|
||||
* @return Comment
|
||||
*/
|
||||
public function setCreatedAt(\DateTime $createdAt): Comment
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function getUser(): User
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return Comment
|
||||
*/
|
||||
public function setUser(User $user): Comment
|
||||
{
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify data which should be serialized to JSON
|
||||
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
* @return mixed data which can be serialized by <b>json_encode</b>,
|
||||
* which is a value of any type other than a resource.
|
||||
* @since 5.4.0
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'text' => $this->getText(),
|
||||
'user' => $this->getUser(),
|
||||
'createdAt' => $this->getCreatedAt()
|
||||
? $this->getCreatedAt()->format("Y-m-d H:i:s")
|
||||
: null,
|
||||
];
|
||||
}
|
||||
}
|
||||
8
src/App/Entity/News.php
Normal file
8
src/App/Entity/News.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
class News
|
||||
{
|
||||
|
||||
}
|
||||
67
src/App/Entity/User.php
Normal file
67
src/App/Entity/User.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
class User implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $username;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $displayName;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUsername(): string
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $username
|
||||
* @return User
|
||||
*/
|
||||
public function setUsername(string $username): User
|
||||
{
|
||||
$this->username = $username;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDisplayName(): string
|
||||
{
|
||||
return $this->displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $displayName
|
||||
* @return User
|
||||
*/
|
||||
public function setDisplayName(string $displayName): User
|
||||
{
|
||||
$this->displayName = $displayName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify data which should be serialized to JSON
|
||||
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
* @return mixed data which can be serialized by <b>json_encode</b>,
|
||||
* which is a value of any type other than a resource.
|
||||
* @since 5.4.0
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'username' => $this->getUsername(),
|
||||
'displayName' => $this->getDisplayName(),
|
||||
];
|
||||
}
|
||||
}
|
||||
397
src/App/Service/SkiesClientService.php
Normal file
397
src/App/Service/SkiesClientService.php
Normal file
@@ -0,0 +1,397 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Comment;
|
||||
use App\Entity\User;
|
||||
use GuzzleHttp\Client;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Zend\Dom\Document;
|
||||
use Zend\Expressive\Exception\MissingDependencyException;
|
||||
|
||||
class SkiesClientService
|
||||
{
|
||||
const SKIES_MAIN_URL = "https://skies.sigmatechnology.se/main.asp";
|
||||
const SKIES_PROFILE_URL = "https://skies.sigmatechnology.se/main.asp?rID=1&alt=2&username=%s";
|
||||
const SKIES_ACTIVITIES_URL = "https://skies.sigmatechnology.se/main.asp?rID=2";
|
||||
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";
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $authHeader = null;
|
||||
|
||||
public function __construct(Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $authHeader
|
||||
* @return SkiesClientService
|
||||
*/
|
||||
public function setAuthHeader(string $authHeader): SkiesClientService
|
||||
{
|
||||
$this->authHeader = $authHeader;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNews()
|
||||
{
|
||||
$response = $this->doSkiesRequest('GET', self::SKIES_MAIN_URL);
|
||||
$htmlBody = $response->getBody();
|
||||
return $this->parseMainPage($htmlBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Activity[]
|
||||
*/
|
||||
public function getActivities()
|
||||
{
|
||||
$response = $this->doSkiesRequest('GET', self::SKIES_ACTIVITIES_URL);
|
||||
$htmlBody = $response->getBody();
|
||||
return $this->parseActivitiesPage($htmlBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $htmlBody
|
||||
* @return Activity[]
|
||||
*/
|
||||
private function parseActivitiesPage(string $htmlBody)
|
||||
{
|
||||
$domDocument = new Document($htmlBody);
|
||||
$eventNodes = Document\Query::execute(
|
||||
"div.container div.row div.box > table tr",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_CSS
|
||||
);
|
||||
|
||||
$activities = [];
|
||||
|
||||
for ($i = 1; $i < $eventNodes->count(); $i++) {
|
||||
$eventRow = $eventNodes[$i];
|
||||
$rowCells = Document\Query::execute(
|
||||
"./td",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$eventRow
|
||||
);
|
||||
|
||||
$href = $rowCells[0]->childNodes->item(0)->getAttribute("href");
|
||||
$queryString = parse_url($href, PHP_URL_QUERY);
|
||||
parse_str($queryString, $queryParams);
|
||||
$activities[] = $this->getActivity($queryParams["aktID"]);
|
||||
}
|
||||
|
||||
return $activities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Activity
|
||||
*/
|
||||
public function getActivity(int $id): Activity
|
||||
{
|
||||
$response = $this->doSkiesRequest('GET', sprintf(self::SKIES_ACTIVITY_URL, $id));
|
||||
$htmlBody = $response->getBody();
|
||||
return $this->parseActivityPage($htmlBody, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Activity
|
||||
*/
|
||||
public function signUpActivity(int $id): Activity
|
||||
{
|
||||
$this->doSkiesRequest('POST', sprintf(self::SKIES_ACTIVITY_SIGNUP_URL, $id), [
|
||||
'form_params' => [
|
||||
'user' => $this->getUsername(),
|
||||
],
|
||||
]);
|
||||
return $this->getActivity($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Activity
|
||||
*/
|
||||
public function signOffActivity(int $id): Activity
|
||||
{
|
||||
$username = $this->getUsername();
|
||||
$this->doSkiesRequest('GET', sprintf(self::SKIES_ACTIVITY_SIGNOFF_URL, $id, $username));
|
||||
return $this->getActivity($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $htmlBody
|
||||
* @param int $id
|
||||
* @return Activity
|
||||
*/
|
||||
private function parseActivityPage(string $htmlBody, int $id): Activity
|
||||
{
|
||||
$domDocument = new Document($htmlBody);
|
||||
/** Activity body */
|
||||
$activityNode = Document\Query::execute(
|
||||
"div.col-md-10 div.box",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_CSS
|
||||
);
|
||||
|
||||
/** Activity name */
|
||||
$h5Nodes = Document\Query::execute(
|
||||
"./h5",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$activityNode[0]
|
||||
);
|
||||
|
||||
$divNodes = Document\Query::execute(
|
||||
".//div",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$activityNode[0]
|
||||
);
|
||||
|
||||
/** Comment block */
|
||||
$commentNodes = Document\Query::execute(
|
||||
'.//div[@class="onecomment"]',
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$activityNode[0]
|
||||
);
|
||||
|
||||
/** Signed users block */
|
||||
$signedUserParagraph = Document\Query::execute(
|
||||
'//div[@class="portlet"]//div[@class="paragraph"]/text()',
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH
|
||||
);
|
||||
|
||||
preg_match("#Date:.*?([0-9]{4}-[0-9]{2}-[0-9]{2}).*?Time: ([0-9]{1,2}:[0-9]{2}).*?Final entry day:.*?([0-9]{4}-[0-9]{2}-[0-9]{2}).*?Accountable: (.*?) / ([0-9 +]*)#msi", $divNodes[1]->textContent, $matches);
|
||||
|
||||
$signedUsers = $this->parseActivitySignedUsers($signedUserParagraph);
|
||||
$isSignedUp = in_array($this->getDisplayName($this->getUsername()), $signedUsers);
|
||||
$canChangeSignup = $isSignedUp
|
||||
? $this->canSignOff($domDocument, $activityNode[0])
|
||||
: $this->canSignup($domDocument, $activityNode[0]);
|
||||
|
||||
$activity = new Activity();
|
||||
$activity->setId($id)
|
||||
->setName($this->clearTextNode($h5Nodes[0]->textContent))
|
||||
->setDescription($this->parseActivityDescription($activityNode[0]))
|
||||
->setDate(new \DateTime(sprintf("%s %s", $matches[1], $matches[2])))
|
||||
->setFinalEntry(new \DateTime($matches[3]))
|
||||
->setAccountable(str_replace(
|
||||
" ",
|
||||
" ",
|
||||
$matches[5]
|
||||
? sprintf("%s (%s)", $matches[4], $matches[5])
|
||||
: $matches[4])
|
||||
)
|
||||
->setSignedUsers($signedUsers)
|
||||
->setIsSignedup($isSignedUp)
|
||||
->setCanChangeSignup($canChangeSignup);
|
||||
$this->parseActivityComments($commentNodes, $activity);
|
||||
|
||||
return $activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DOMNode $element
|
||||
* @return null|string
|
||||
*/
|
||||
private function parseActivityDescription(\DOMNode $element): ?string
|
||||
{
|
||||
$description = "";
|
||||
$isContent = false;
|
||||
/** @var \DOMElement $childNode */
|
||||
foreach ($element->childNodes as $childNode) {
|
||||
if ($childNode->nodeName == "hr") {
|
||||
$isContent = true;
|
||||
}
|
||||
if ($childNode->nodeName == "form") {
|
||||
break;
|
||||
}
|
||||
if ($childNode->nodeName == "span") {
|
||||
break;
|
||||
}
|
||||
if ($childNode->nodeName == "script") {
|
||||
break;
|
||||
}
|
||||
if ($isContent) {
|
||||
$description .= $childNode->nodeName == "br"
|
||||
? "\n"
|
||||
: rtrim($childNode->textContent);
|
||||
}
|
||||
}
|
||||
return $this->clearTextNode($description);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document\NodeList $commentElements
|
||||
* @param Activity $activity
|
||||
*/
|
||||
private function parseActivityComments(Document\NodeList $commentElements, Activity $activity)
|
||||
{
|
||||
/** @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]
|
||||
)));
|
||||
$activity->addComment($comment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document\NodeList $usersBlockText
|
||||
* @return array
|
||||
* @todo remove unsign button if it is present
|
||||
*/
|
||||
private function parseActivitySignedUsers(Document\NodeList $usersBlockText): array
|
||||
{
|
||||
$signed = [];
|
||||
for ($i = 1; $i < $usersBlockText->count(); $i++) {
|
||||
preg_match(
|
||||
"#[0-9]+\.[^\p{L}]([\p{L}\s]+)#msiu",
|
||||
$usersBlockText[$i]->textContent,
|
||||
$usernameMatch
|
||||
);
|
||||
$signed[] = $usernameMatch[1];
|
||||
}
|
||||
$collator = new \Collator("hu_HU");
|
||||
$collator->sort($signed);
|
||||
return $signed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can sign off if there is no red span inside the node
|
||||
* @param Document $domDocument
|
||||
* @param \DOMNode $domNode
|
||||
* @return bool
|
||||
*/
|
||||
private function canSignOff(Document $domDocument, \DOMNode $domNode): bool
|
||||
{
|
||||
$redSpanNodes = Document\Query::execute(
|
||||
'./span[@class="red"]',
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$domNode
|
||||
);
|
||||
return $redSpanNodes->count() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can sign up if there is a form direct descendant
|
||||
* @param Document $domDocument
|
||||
* @param \DOMNode $domNode
|
||||
* @return bool
|
||||
*/
|
||||
private function canSignUp(Document $domDocument, \DOMNode $domNode): bool
|
||||
{
|
||||
$formNodes = Document\Query::execute(
|
||||
"./form",
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH,
|
||||
$domNode
|
||||
);
|
||||
return $formNodes->count() == 1;
|
||||
}
|
||||
|
||||
private function parseMainPage(string $htmlBody)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getDisplayName(string $username): string
|
||||
{
|
||||
$response = $this->doSkiesRequest("GET", sprintf(self::SKIES_PROFILE_URL, $username));
|
||||
$profilePage = $response->getBody();
|
||||
|
||||
$domDocument = new Document($profilePage);
|
||||
$h1Nodes = Document\Query::execute(
|
||||
'//div[@class="box"]/h1',
|
||||
$domDocument,
|
||||
Document\Query::TYPE_XPATH
|
||||
);
|
||||
return $this->clearTextNode($h1Nodes[0]->textContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear junk from text nodes
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
private function clearTextNode(string $text): string
|
||||
{
|
||||
$text = str_replace(" ", " ", $text);
|
||||
$text = str_replace("", "-", $text);
|
||||
$text = preg_replace("#[ \t]+#msiu", " ", $text);
|
||||
return trim($text, " \t\n\r\0\x0B" . chr(0xC2) . chr(0xA0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Do an http request adding the Authorization header
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $url
|
||||
* @param array $options
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
private function doSkiesRequest(string $method, string $url, $options = []): ResponseInterface
|
||||
{
|
||||
if ($this->authHeader == null) {
|
||||
throw new MissingDependencyException("X-Passthru-Auth header is missing");
|
||||
}
|
||||
return $this->client
|
||||
->request($method, $url, [
|
||||
'headers' => [
|
||||
'Authorization' => "Basic {$this->authHeader}",
|
||||
]
|
||||
] + $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getUsername(): string
|
||||
{
|
||||
if (null == $this->authHeader) {
|
||||
throw new MissingDependencyException("X-Passthru-Auth header is missing");
|
||||
}
|
||||
$decodedHeader = base64_decode($this->authHeader);
|
||||
list($username) = explode(":", $decodedHeader);
|
||||
return $username;
|
||||
}
|
||||
}
|
||||
17
src/App/Service/SkiesClientServiceFactory.php
Normal file
17
src/App/Service/SkiesClientServiceFactory.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class SkiesClientServiceFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$httpClient = new Client([
|
||||
'cookies' => true,
|
||||
]);
|
||||
return new SkiesClientService($httpClient);
|
||||
}
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Symfony\Component\CssSelector\CssSelectorConverter;
|
||||
use Zend\Http\Client;
|
||||
|
||||
/**
|
||||
* Class SkiesService
|
||||
*
|
||||
* @package App\Service
|
||||
* @todo handle errors in http response
|
||||
*/
|
||||
class SkiesService
|
||||
{
|
||||
const BASE_URI = 'http://skies.sigmatechnology.se/';
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $httpClient;
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->httpClient = new Client();
|
||||
$headers = $this->httpClient->getRequest()->getHeaders();
|
||||
$headers->addHeaderLine('Authorization', 'Basic ' . $this->getAuthToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all activities
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getActivityList()
|
||||
{
|
||||
$this->httpClient->setUri(self::BASE_URI . "main.asp?rID=2");
|
||||
$skiesResponse = $this->httpClient->send();
|
||||
$skiesHtmlBody = $skiesResponse->getBody();
|
||||
|
||||
$cssToXpathConverter = new CssSelectorConverter();
|
||||
$xpathQuery = $cssToXpathConverter->toXPath('html > body > div > div.row > div.col-md-10 > div.row > div.col-md-9 > div.box > table.table-striped > tr');
|
||||
|
||||
$doc = new \DOMDocument();
|
||||
$doc->loadHTML($skiesHtmlBody);
|
||||
|
||||
$xpath = new \DOMXPath($doc);
|
||||
$elements = $xpath->query($xpathQuery);
|
||||
|
||||
$parsed = [];
|
||||
/** @var \DOMNode $domElement */
|
||||
foreach ($elements as $domElement) {
|
||||
if($domElement->childNodes->item(0)->nodeName != 'td') {
|
||||
continue;
|
||||
}
|
||||
$url = $domElement->childNodes->item(0)->childNodes->item(0)->attributes->getNamedItem('href')->textContent;
|
||||
preg_match("/aktid=([0-9]+)/msi", $url, $match);
|
||||
$parsed[] = [
|
||||
'id' => (int)$match[1],
|
||||
'label' => $domElement->childNodes->item(0)->childNodes->item(0)->textContent,
|
||||
'date' => $domElement->childNodes->item(2)->textContent,
|
||||
'time' => trim($domElement->childNodes->item(3)->textContent, " \t\n\r\0\x0B\xc2\xa0"),
|
||||
];
|
||||
}
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single activity
|
||||
*
|
||||
* @param int $id
|
||||
* @return array
|
||||
*/
|
||||
public function getActivity(int $id)
|
||||
{
|
||||
$this->httpClient->setUri(self::BASE_URI . "main.asp?rID=2&alt=1&aktID=" . $id);
|
||||
$skiesResponse = $this->httpClient->send();
|
||||
$skiesHtmlBody = $skiesResponse->getBody();
|
||||
|
||||
$cssToXpathConverter = new CssSelectorConverter();
|
||||
$xpathQuery = $cssToXpathConverter->toXPath('div.container > div.row > div.col-md-10 > div.row > div.col-md-9 > div.box');
|
||||
$xpathCommentsQuery = $cssToXpathConverter->toXPath('div.container div.paragraph > div.onecomment');
|
||||
|
||||
$doc = new \DOMDocument();
|
||||
$doc->loadHTML($skiesHtmlBody);
|
||||
|
||||
$xpath = new \DOMXPath($doc);
|
||||
$elements = $xpath->query($xpathQuery);
|
||||
|
||||
$h5Elements = $elements->item(0)->getElementsByTagName('h5');
|
||||
$title = $h5Elements->item(0)->textContent;
|
||||
|
||||
$detailDivElements = $elements->item(0)->getElementsByTagName('div');
|
||||
$commentElements = $xpath->query($xpathCommentsQuery);
|
||||
|
||||
$eventDetails = $this->parseActivityDetails($detailDivElements->item(1)->textContent);
|
||||
$eventDescription = $this->parseActivityDescription($elements->item(0));
|
||||
$eventComments = $this->parseActivityComments($commentElements);
|
||||
|
||||
return [
|
||||
'title' => $title,
|
||||
'details' => $eventDetails,
|
||||
'description' => $eventDescription,
|
||||
'comments' => $eventComments,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
* @todo real auth token from whatever...
|
||||
*/
|
||||
private function getAuthToken(): ?string
|
||||
{
|
||||
$config = $this->container->get('config');
|
||||
return $config['authKey'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the activity information details returning the date, time finaly entry and the person accountable
|
||||
*
|
||||
* @param string $divText
|
||||
* @return array|null
|
||||
*/
|
||||
private function parseActivityDetails(string $divText): ?array
|
||||
{
|
||||
preg_match("#Date:.*?([0-9]{4}-[0-9]{2}-[0-9]{2}).*?Time: ([0-9]{1,2}:[0-9]{2}).*?Final entry day:.*?([0-9]{4}-[0-9]{2}-[0-9]{2}).*?Accountable: (.*?) / ([0-9 +]*)#msi", $divText, $matches);
|
||||
return [
|
||||
'date' => $matches[1],
|
||||
'time' => $matches[2],
|
||||
'finalEntry' => $matches[3],
|
||||
'accountable' => str_replace(" ", " ", $matches[5] ? sprintf("%s (%s)", $matches[4], $matches[5]) : $matches[4]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses comment block. Comment section is pretty much unformatted text
|
||||
* between a <hr> tag and a <form> tag in the passed $element
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @return null|string
|
||||
*/
|
||||
private function parseActivityDescription(\DOMElement $element): ?string
|
||||
{
|
||||
$description = "";
|
||||
$isContent = false;
|
||||
/** @var \DOMElement $childNode */
|
||||
foreach($element->childNodes as $childNode) {
|
||||
if ($childNode->nodeName == "hr") { $isContent = true; }
|
||||
if ($childNode->nodeName == "form") { break; }
|
||||
if ($isContent) {
|
||||
$description .= $childNode->nodeName == "br"
|
||||
? "\n"
|
||||
: rtrim($childNode->textContent);
|
||||
}
|
||||
}
|
||||
return trim($description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse $commentElements
|
||||
*
|
||||
* @param \DOMNodeList $commentElements
|
||||
* @return array|null
|
||||
*/
|
||||
private function parseActivityComments(\DOMNodeList $commentElements): ?array
|
||||
{
|
||||
$comments = [];
|
||||
/** @var \DOMElement $commentElement */
|
||||
foreach($commentElements as $commentElement) {
|
||||
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(" "," ", $commentElement->getElementsByTagName("div")->item(2)->textContent), $matches);
|
||||
$comments[] = [
|
||||
'comment' => $commentElement->getElementsByTagName("div")->item(1)->textContent,
|
||||
'user' => $matches[1],
|
||||
'date' => $matches[2],
|
||||
'time' => $matches[3],
|
||||
];
|
||||
}
|
||||
return $comments;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class SkiesServiceFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
return new SkiesService($container);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user