Browse code

First iteration of filterable joblist

Benjamin Roth authored on01/02/2023 22:36:09
Showing6 changed files
... ...
@@ -17,7 +17,8 @@
17 17
   "require":{
18 18
     "php": "^7.4 || ^8.0",
19 19
     "contao/core-bundle": "^4.13",
20
-    "symfony/http-client": "^5.4"
20
+    "symfony/http-client": "^5.4",
21
+    "symfony/serializer": "^5.4"
21 22
   },
22 23
   "conflict": {
23 24
     "contao/manager-plugin": "<2.0 || >=3.0"
... ...
@@ -0,0 +1,57 @@
1
+{% extends '@Contao/block_unsearchable' %}
2
+
3
+{% block content %}
4
+    {% if jobs is not defined %}
5
+        <p>Es wurden keine Stellenangebote gefunden!</p>
6
+    {% else %}
7
+        <form class="filter" method="get">
8
+            <div class="formbody">
9
+                <input type="hidden" name="FORM_SUBMIT" value="{{ formSubmit }}">
10
+                <div class="widget widget-text">
11
+                    <input type="text" name="filter_keywords" placeholder="Jobtitel" value="{{ formSetFilters.filter_keywords ?? '' }}">
12
+                </div>
13
+                {% if filterVertragsarten is defined %}
14
+                    <div class="widget widget-select">
15
+                        <select name="filter_vertragsart">
16
+                            <option value="">Art der Anstellung</option>
17
+                            {% for vertragsart in filterVertragsarten %}
18
+                                <option value="{{ vertragsart.ObjectUuid }}"{% if formSetFilters.filter_vertragsart is defined and formSetFilters.filter_vertragsart == vertragsart.ObjectUuid %} selected{% endif %}>{{ vertragsart.Bezeichnung }}</option>
19
+                            {% endfor %}
20
+                        </select>
21
+                    </div>
22
+                {% endif %}
23
+                {% if filterAbteilung is defined %}
24
+                    <div class="widget widget-select">
25
+                        <select name="filter_abteilung">
26
+                            <option value="">Unternehmensbereich / Abteilung</option>
27
+                            {% for abteilung in filterAbteilung %}
28
+                                <option value="{{ abteilung.ObjectUuid }}"{% if formSetFilters.filter_abteilung is defined and formSetFilters.filter_abteilung == abteilung.ObjectUuid %} selected{% endif %}>{{ abteilung.Bezeichnung }}</option>
29
+                            {% endfor %}
30
+                        </select>
31
+                    </div>
32
+                {% endif %}
33
+                <div class="widget widget-submit">
34
+                    <button type="submit">Suchen</button>
35
+                </div>
36
+            </div>
37
+        </form>
38
+
39
+        <div class="jobs">
40
+            <ul>
41
+            {% for job in jobs %}
42
+                <li>
43
+                    <h3>{{ job.Bezeichnung }}</h3>
44
+                    <div class="meta">
45
+                        <dl>
46
+                            <dt>Einsatzort:</dt><dd>{{ job.EinsatzortPlz }} {{ job.EinsatzortOrt }}</dd>
47
+                            <dt>Vertragsart:</dt><dd>{{ job.Vertragsarten }}</dd>
48
+                            <dt>Beginn:</dt><dd>{{ job.BeginnAbSofort ? 'ab sofort' : (job.Beginn ? job.Beginn|date("d.m.Y") : '') }}</dd>
49
+                            <dt>Eintrag vom:</dt><dd>{{ job.DatumAb ? job.DatumAb|date("d.m.Y") : '' }}</dd>
50
+                        </dl>
51
+                    </div>
52
+                </li>
53
+            {% endfor %}
54
+            </ul>
55
+        </div>
56
+    {% endif %}
57
+{% endblock %}
0 58
new file mode 100644
... ...
@@ -0,0 +1,127 @@
1
+<?php
2
+
3
+declare(strict_types=1);
4
+
5
+/*
6
+ * This file is part of alox bundle for Contao.
7
+ *
8
+ * (c) Benjamin Roth
9
+ *
10
+ * @license commercial
11
+ */
12
+
13
+namespace vossmedien\AloxBundle\API;
14
+
15
+use Contao\System;
16
+use Symfony\Component\Serializer\SerializerInterface;
17
+use Symfony\Contracts\HttpClient\HttpClientInterface;
18
+use vossmedien\AloxBundle\Model\KatalogModel;
19
+use vossmedien\AloxBundle\Model\StellenModel;
20
+
21
+class Zvoove
22
+{
23
+    /**
24
+     * @var SerializerInterface
25
+     */
26
+    protected $serializer;
27
+
28
+    /**
29
+     * @var HttpClientInterface
30
+     */
31
+    protected $httpClient;
32
+
33
+    protected $apiKey;
34
+
35
+    protected $apiDomain;
36
+
37
+    public function __construct(SerializerInterface $serializer, HttpClientInterface $httpClient)
38
+    {
39
+        $this->serializer = $serializer;
40
+        $this->httpClient = $httpClient;
41
+
42
+        $this->apiKey = System::getContainer()->getParameter('vossmedien_alox.zvoove.api_key');
43
+        $this->apiDomain = System::getContainer()->getParameter('vossmedien_alox.zvoove.api_domain');
44
+    }
45
+
46
+    protected function getApiKey()
47
+    {
48
+        return $this->apiKey;
49
+    }
50
+
51
+    protected function getApiDomain()
52
+    {
53
+        return rtrim($this->apiDomain,'/');
54
+    }
55
+
56
+    protected function getAuthorizeRequestHeader()
57
+    {
58
+        $header = [
59
+            'X-ApiKey' => $this->getApiKey()
60
+        ];
61
+
62
+        return $header;
63
+    }
64
+
65
+    protected function sendRequest(string $relEndpoint, array $options, string $method = 'GET')
66
+    {
67
+        $relEndpoint = '/' . ltrim($relEndpoint,'/');
68
+
69
+        return $this->httpClient->request($method,$this->getApiDomain().$relEndpoint,$options);
70
+    }
71
+
72
+    public function getStellenFiltered(array $params=[]): ?StellenModel
73
+    {
74
+        $options = [
75
+            'headers' => $this->getAuthorizeRequestHeader()
76
+        ];
77
+
78
+        if (count($params))
79
+        {
80
+            $options['query'] = $params;
81
+        }
82
+
83
+        $response = $this->sendRequest('Stelle/GetStellenFiltered',$options);
84
+
85
+
86
+
87
+        if ($response->getStatusCode() == 200)
88
+        {
89
+            $content = $response->getContent();
90
+
91
+            /** @var StellenModel $collection */
92
+            $collection = $this->serializer->deserialize($content,StellenModel::class,'json');
93
+
94
+            return $collection;
95
+        }
96
+
97
+        return null;
98
+    }
99
+
100
+    public function getKatalogByRelationName(string $entityName, string $relationName): ?KatalogModel
101
+    {
102
+        $options = [
103
+            'headers' => $this->getAuthorizeRequestHeader(),
104
+            'query' => [
105
+                'entityName' => $entityName,
106
+                'relationName' => $relationName
107
+            ]
108
+        ];
109
+
110
+        $response = $this->sendRequest('Katalog/GetByRelationName',$options);
111
+
112
+
113
+
114
+        if ($response->getStatusCode() == 200)
115
+        {
116
+            $content = $response->getContent();
117
+
118
+            /** @var KatalogModel $collection */
119
+            $collection = $this->serializer->deserialize($content,KatalogModel::class,'json');
120
+
121
+            return $collection;
122
+        }
123
+
124
+        return null;
125
+    }
126
+
127
+}
... ...
@@ -14,12 +14,12 @@ namespace vossmedien\AloxBundle\Controller\Frontend\Module;
14 14
 
15 15
 use Contao\CoreBundle\Controller\FrontendModule\AbstractFrontendModuleController;
16 16
 use Contao\CoreBundle\ServiceAnnotation\FrontendModule;
17
+use Contao\Input;
17 18
 use Contao\ModuleModel;
18
-use Contao\System;
19 19
 use Contao\Template;
20
-use Symfony\Component\HttpClient\HttpClient;
21 20
 use Symfony\Component\HttpFoundation\Request;
22 21
 use Symfony\Component\HttpFoundation\Response;
22
+use vossmedien\AloxBundle\API\Zvoove;
23 23
 
24 24
 /**
25 25
  * @FrontendModule(JoblistModuleController::TYPE, category="miscellaneous")
... ...
@@ -28,24 +28,75 @@ class JoblistModuleController extends AbstractFrontendModuleController
28 28
 {
29 29
     public const TYPE = 'alox_joblist';
30 30
 
31
+    /**
32
+     * @var Zvoove
33
+     */
34
+    protected $api;
35
+
36
+    public function __construct(Zvoove $api)
37
+    {
38
+        $this->api = $api;
39
+    }
40
+
41
+
31 42
     protected function getResponse(Template $template, ModuleModel $model, Request $request): ?Response
32 43
     {
33
-        $apiKey = System::getContainer()->getParameter('vossmedien_alox.zvoove.api_key');
34
-        $apiDomain = System::getContainer()->getParameter('vossmedien_alox.zvoove.api_domain');
44
+        $strFormId = 'joblist-form-' . $model->id;
45
+        $arrSearchParams = [];
46
+        $arrSetFilters = [];
47
+
48
+        // Prepare search parameters
49
+        if (Input::get('FORM_SUBMIT') == $strFormId)
50
+        {
51
+            if (Input::get('filter_keywords'))
52
+            {
53
+                $arrSearchParams['keywords'] = Input::get('filter_keywords');
54
+                $arrSetFilters['filter_keywords'] = Input::get('filter_keywords');
55
+            }
56
+
57
+            if (Input::get('filter_vertragsart'))
58
+            {
59
+                $arrSearchParams['vaUuids'] = Input::get('filter_vertragsart');
60
+                $arrSetFilters['filter_vertragsart'] = Input::get('filter_vertragsart');
61
+            }
62
+
63
+            if (Input::get('filter_abteilung'))
64
+            {
65
+                $arrSearchParams['abtUuids'] = Input::get('filter_abteilung');
66
+                $arrSetFilters['filter_abteilung'] = Input::get('filter_abteilung');
67
+            }
68
+        }
69
+
70
+        // Get (filtered) jobs
71
+        $jobs = $this->api->getStellenFiltered($arrSearchParams);
72
+
73
+
74
+        // Get filter options
75
+        $filterVertragsarten = $this->api->getKatalogByRelationName('StelleVertragsart','ChildEntity');
76
+        $filterAbteilung = $this->api->getKatalogByRelationName('StelleAbteilung','Abteilung');
77
+
78
+
79
+        // Populate template vars
80
+        if ($jobs !== null && $jobs->TotalItems > 0)
81
+        {
82
+            $template->jobs = $jobs;
83
+        }
35 84
 
36
-        $httpClient = HttpClient::create();
85
+        if ($filterVertragsarten !== null && $filterVertragsarten->TotalItems > 0)
86
+        {
87
+            $template->filterVertragsarten = $filterVertragsarten;
88
+        }
37 89
 
38
-        $header = [
39
-            'headers' => [
40
-                'X-ApiKey' => $apiKey
41
-            ]
42
-        ];
90
+        if ($filterAbteilung !== null && $filterAbteilung->TotalItems > 0)
91
+        {
92
+            $template->filterAbteilung = $filterAbteilung;
93
+        }
43 94
 
44
-        $response = $httpClient->request('GET',$apiDomain, $header);
95
+        $template->formSubmit = $strFormId;
96
+        $template->formSetFilters = $arrSetFilters;
45 97
 
46
-        dump($response->getContent());
47 98
 
48
-        return new Response();
99
+        return $template->getResponse();
49 100
     }
50 101
 
51 102
 }
52 103
new file mode 100644
... ...
@@ -0,0 +1,85 @@
1
+<?php
2
+
3
+declare(strict_types=1);
4
+
5
+/*
6
+ * This file is part of alox bundle for Contao.
7
+ *
8
+ * (c) Benjamin Roth
9
+ *
10
+ * @license commercial
11
+ */
12
+
13
+namespace vossmedien\AloxBundle\Model;
14
+
15
+class KatalogModel implements \ArrayAccess, \Countable, \IteratorAggregate
16
+{
17
+    /**
18
+     * @var int
19
+     */
20
+    private int $TotalItems;
21
+
22
+    /**
23
+     * @var array
24
+     */
25
+    private array $Items;
26
+
27
+    public function __get($name)
28
+    {
29
+        if (isset($this->{$name}) && method_exists($this,'get'.$name))
30
+        {
31
+            return $this->{'get'.$name}();
32
+        }
33
+    }
34
+
35
+
36
+    public function getItems(): array
37
+    {
38
+        return $this->Items;
39
+    }
40
+
41
+    public function getTotalItems(): int
42
+    {
43
+        return $this->TotalItems;
44
+    }
45
+
46
+    public function setItems(array $items): void
47
+    {
48
+        $this->Items = $items;
49
+    }
50
+
51
+    public function setTotalItems(int $total): void
52
+    {
53
+        $this->TotalItems = $total;
54
+    }
55
+
56
+    public function getIterator()
57
+    {
58
+        return new \ArrayIterator($this->Items);
59
+    }
60
+
61
+    public function offsetExists($offset)
62
+    {
63
+        return isset($this->Items[$offset]);
64
+    }
65
+
66
+    public function offsetGet($offset)
67
+    {
68
+        return $this->Items[$offset];
69
+    }
70
+
71
+    public function offsetSet($offset, $value)
72
+    {
73
+        throw new \RuntimeException('This collection is immutable');
74
+    }
75
+
76
+    public function offsetUnset($offset)
77
+    {
78
+        throw new \RuntimeException('This collection is immutable');
79
+    }
80
+
81
+    public function count()
82
+    {
83
+        return \count($this->Items);
84
+    }
85
+}
0 86
new file mode 100644
... ...
@@ -0,0 +1,102 @@
1
+<?php
2
+
3
+declare(strict_types=1);
4
+
5
+/*
6
+ * This file is part of alox bundle for Contao.
7
+ *
8
+ * (c) Benjamin Roth
9
+ *
10
+ * @license commercial
11
+ */
12
+
13
+namespace vossmedien\AloxBundle\Model;
14
+
15
+use \DateTime;
16
+
17
+class StellenModel implements \ArrayAccess, \Countable, \IteratorAggregate
18
+{
19
+    /**
20
+     * @var int
21
+     */
22
+    private int $TotalItems;
23
+
24
+    /**
25
+     * @var DateTime
26
+     */
27
+    private DateTime $LastUpdateTime;
28
+
29
+    /**
30
+     * @var array
31
+     */
32
+    private array $Items;
33
+
34
+    public function __get($name)
35
+    {
36
+        if (isset($this->{$name}) && method_exists($this,'get'.$name))
37
+        {
38
+            return $this->{'get'.$name}();
39
+        }
40
+    }
41
+
42
+
43
+    public function getItems(): array
44
+    {
45
+        return $this->Items;
46
+    }
47
+
48
+    public function getLastUpdateTime(): DateTime
49
+    {
50
+        return $this->LastUpdateTime;
51
+    }
52
+
53
+    public function getTotalItems(): int
54
+    {
55
+        return $this->TotalItems;
56
+    }
57
+
58
+    public function setItems(array $items): void
59
+    {
60
+        $this->Items = $items;
61
+    }
62
+
63
+    public function setLastUpdateTime(string $updateTime): void
64
+    {
65
+        $this->LastUpdateTime = new DateTime($updateTime);
66
+    }
67
+
68
+    public function setTotalItems(int $total): void
69
+    {
70
+        $this->TotalItems = $total;
71
+    }
72
+
73
+    public function getIterator()
74
+    {
75
+        return new \ArrayIterator($this->Items);
76
+    }
77
+
78
+    public function offsetExists($offset)
79
+    {
80
+        return isset($this->Items[$offset]);
81
+    }
82
+
83
+    public function offsetGet($offset)
84
+    {
85
+        return $this->Items[$offset];
86
+    }
87
+
88
+    public function offsetSet($offset, $value)
89
+    {
90
+        throw new \RuntimeException('This collection is immutable');
91
+    }
92
+
93
+    public function offsetUnset($offset)
94
+    {
95
+        throw new \RuntimeException('This collection is immutable');
96
+    }
97
+
98
+    public function count()
99
+    {
100
+        return \count($this->Items);
101
+    }
102
+}