Browse code

Implement ajax controller for geo data retrieval

Benjamin Roth authored on02/02/2023 23:52:47
Showing6 changed files
... ...
@@ -20,6 +20,9 @@
20 20
     "symfony/http-client": "^5.4",
21 21
     "symfony/serializer": "^5.4"
22 22
   },
23
+  "require-dev": {
24
+    "contao/manager-plugin": "^2.0"
25
+  },
23 26
   "conflict": {
24 27
     "contao/manager-plugin": "<2.0 || >=3.0"
25 28
   },
26 29
new file mode 100644
... ...
@@ -0,0 +1,3 @@
1
+alox.frontend.controllers:
2
+    resource: "@VossmedienAloxBundle/src/Controller/Frontend"
3
+    type: annotation
0 4
new file mode 100644
... ...
@@ -0,0 +1,52 @@
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
+$GLOBALS['TL_DCA']['tl_ab_geodb'] = [
14
+    'config' => [
15
+        'sql' => [
16
+            'keys' => [
17
+                'id' => 'primary',
18
+                'name,postal' => 'index',
19
+                'name,postal,type' => 'index'
20
+            ]
21
+        ]
22
+    ],
23
+    'fields' => [
24
+        'id' => [
25
+            'sql' => "int(10) unsigned NOT NULL auto_increment"
26
+        ],
27
+        'tmp' => [
28
+            'sql' => "varchar(10) unsigned NOT NULL 0"
29
+        ],
30
+        'pid' => [
31
+            'sql' => "int(10) unsigned NOT NULL 0"
32
+        ],
33
+        'name' => [
34
+            'sql' => "varchar(64) NOT NULL default ''"
35
+        ],
36
+        'type' => [
37
+            'sql' => "varchar(32) NOT NULL default ''"
38
+        ],
39
+        'postal' => [
40
+            'sql' => "varchar(512) NOT NULL default ''"
41
+        ],
42
+        'lat' => [
43
+            'sql' => "float(9,6) NOT NULL default 0"
44
+        ],
45
+        'lon' => [
46
+            'sql' => "float(9,6) NOT NULL default 0"
47
+        ],
48
+        'invalid' => [
49
+            'sql' => "char(1) unsigned NOT NULL '0'"
50
+        ],
51
+    ]
52
+];
... ...
@@ -49,6 +49,19 @@
49 49
             new TomSelect("#filter-city-{{ id }}",{
50 50
                 allowEmptyOption: true,
51 51
                 create: false,
52
+                valueField: 'latLon',
53
+                labelField: 'name',
54
+                searchField: 'name',
55
+                load: function(query, callback) {
56
+                    var url = '_geodb/getLatLon?q=' + encodeURIComponent(query);
57
+                    fetch(url)
58
+                        .then(response => response.json())
59
+                        .then(json => {
60
+                            callback(json.items);
61
+                        }).catch(() => {
62
+                        callback();
63
+                    });
64
+                },
52 65
                 onChange: function (values) {
53 66
                     let target = document.getElementById('filter-city-label-{{ id }}');
54 67
                     if (target !== undefined && this.activeOption.innerText !== undefined)
... ...
@@ -14,12 +14,19 @@ namespace vossmedien\AloxBundle\ContaoManager;
14 14
 
15 15
 use Contao\CoreBundle\ContaoCoreBundle;
16 16
 use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
17
+use Contao\ManagerPlugin\Routing\RoutingPluginInterface;
17 18
 use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
18 19
 use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
20
+use Symfony\Component\Config\Loader\LoaderResolverInterface;
21
+use Symfony\Component\HttpKernel\KernelInterface;
22
+use Symfony\Component\Routing\Loader\YamlFileLoader;
19 23
 use vossmedien\AloxBundle\VossmedienAloxBundle;
20 24
 
21
-class Plugin implements BundlePluginInterface
25
+class Plugin implements BundlePluginInterface, RoutingPluginInterface
22 26
 {
27
+    /**
28
+     * {@inheritdoc}
29
+     */
23 30
     public function getBundles(ParserInterface $parser): array
24 31
     {
25 32
         return [
... ...
@@ -27,4 +34,19 @@ class Plugin implements BundlePluginInterface
27 34
                 ->setLoadAfter([ContaoCoreBundle::class]),
28 35
         ];
29 36
     }
37
+
38
+    /**
39
+     * {@inheritdoc}
40
+     */
41
+    public function getRouteCollection(LoaderResolverInterface $resolver, KernelInterface $kernel)
42
+    {
43
+        $config = '@VossmedienAloxBundle/config/routing.yml';
44
+        $loader = $resolver->resolve($config, 'yaml');
45
+
46
+        if ($loader instanceof YamlFileLoader) {
47
+            return $loader->load($config);
48
+        }
49
+
50
+        return null;
51
+    }
30 52
 }
31 53
new file mode 100644
... ...
@@ -0,0 +1,96 @@
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\Controller\Frontend;
14
+
15
+use Contao\CoreBundle\Controller\AbstractController;
16
+use Contao\CoreBundle\Framework\ContaoFramework;
17
+use Doctrine\DBAL\Connection;
18
+use Psr\Container\ContainerInterface;
19
+use Symfony\Component\HttpFoundation\JsonResponse;
20
+use Symfony\Component\HttpFoundation\Request;
21
+use Symfony\Component\HttpFoundation\RequestStack;
22
+use Symfony\Component\Routing\Annotation\Route;
23
+use Symfony\Component\HttpFoundation\Response;
24
+use Symfony\Contracts\Translation\TranslatorInterface;
25
+
26
+class GeodbAjaxController extends AbstractController
27
+{
28
+
29
+    /**
30
+     * @var TranslatorInterface
31
+     */
32
+    protected $translator;
33
+    /**
34
+     * @var Request
35
+     */
36
+    protected $request;
37
+    /**
38
+     * @var ContaoFramework
39
+     */
40
+    protected $framework;
41
+    /**
42
+     * @var Connection
43
+     */
44
+    protected $db;
45
+
46
+
47
+
48
+    public function __construct(ContainerInterface $container, TranslatorInterface $translator, RequestStack $request, ContaoFramework $framework, Connection $connection)
49
+    {
50
+        $this->container = $container;
51
+        $this->initializeContaoFramework();
52
+        $this->translator = $translator;
53
+        $this->request = $request->getCurrentRequest();
54
+        $this->framework = $framework;
55
+        $this->db = $connection;
56
+    }
57
+
58
+
59
+    /**
60
+     * @Route("/_geodb/getLatLon", name="geodb_latlon", defaults={"_scope" = "frontend", "_token_check" = false})
61
+     *
62
+     * @return Response
63
+     */
64
+    public function getLatLon()
65
+    {
66
+        global $objPage;
67
+
68
+        if (isset($_REQUEST['q']))
69
+        {
70
+            $result = [
71
+                'items' => []
72
+            ];
73
+
74
+            $query = $this->db->executeQuery("SELECT lat, lon, postal, name FROM tl_ab_geodb WHERE (name LIKE ? OR postal LIKE ?) AND type IN ('Dorf','Ortsteil','Ortschaft','Ort','Kreisstadt','Gemeinde','Stadt','Stadtteil') AND invalid != '1' AND postal != ''",[
75
+                '%' . $_REQUEST['q'] . '%',
76
+                '%' . $_REQUEST['q'] . '%',
77
+            ]);
78
+
79
+            if ($query->rowCount())
80
+            {
81
+                foreach ($query->fetchAllAssociative() as $item)
82
+                {
83
+                    $result['items'][] = [
84
+                        'latLon' => $item['lat'].','.$item['lon'],
85
+                        'name' => $item['postal'].' '.$item['name']
86
+                    ];
87
+                }
88
+            }
89
+
90
+            return new JsonResponse($result);
91
+        }
92
+
93
+
94
+        return new Response('Required parameter missing',412);
95
+    }
96
+}