... | ... |
@@ -8,6 +8,7 @@ |
8 | 8 |
* @license commercial |
9 | 9 |
*/ |
10 | 10 |
|
11 |
+use vonRotenberg\RealEstateListingBundle\Model\ManagedPropertyModel; |
|
11 | 12 |
use vonRotenberg\RealEstateListingBundle\Model\RealEstateAssetsModel; |
12 | 13 |
use Contao\System; |
13 | 14 |
use Contao\ArrayUtil; |
... | ... |
@@ -17,6 +18,9 @@ ArrayUtil::arrayInsert($GLOBALS['BE_MOD'], 1, [ |
17 | 18 |
'vr_real_estate' => [ |
18 | 19 |
'vr_re_categories' => [ |
19 | 20 |
'tables' => array('tl_vr_real_estate_categories','tl_vr_real_estate_assets') |
21 |
+ ], |
|
22 |
+ 'managed_properties' => [ |
|
23 |
+ 'tables' => ['tl_vr_re_managedProperties'], |
|
20 | 24 |
] |
21 | 25 |
] |
22 | 26 |
]); |
... | ... |
@@ -31,5 +35,6 @@ if ($requestStack->getCurrentRequest() !== null && $scopeMatcher->isBackendReque |
31 | 35 |
|
32 | 36 |
$GLOBALS['TL_MODELS']['tl_vr_real_estate_assets'] = RealEstateAssetsModel::class; |
33 | 37 |
$GLOBALS['TL_MODELS']['tl_vr_real_estate_categories'] = RealEstateCategoriesModel::class; |
38 |
+$GLOBALS['TL_MODELS']['tl_vr_re_managedProperties'] = ManagedPropertyModel::class; |
|
34 | 39 |
|
35 | 40 |
|
... | ... |
@@ -8,6 +8,8 @@ |
8 | 8 |
* @license commercial |
9 | 9 |
*/ |
10 | 10 |
|
11 |
+use vonRotenberg\RealEstateListingBundle\Controller\FrontendModule\ManagedPropertyController; |
|
12 |
+use vonRotenberg\RealEstateListingBundle\Controller\FrontendModule\ManagedPropertyReaderController; |
|
11 | 13 |
use vonRotenberg\RealEstateListingBundle\Controller\FrontendModule\RealEstateAssetsAdController; |
12 | 14 |
use vonRotenberg\RealEstateListingBundle\Controller\FrontendModule\RealEstateAssetsListController; |
13 | 15 |
use vonRotenberg\RealEstateListingBundle\Controller\FrontendModule\RealEstateAssetsReaderController; |
... | ... |
@@ -15,6 +17,23 @@ use vonRotenberg\RealEstateListingBundle\Controller\FrontendModule\RealEstateAss |
15 | 17 |
$GLOBALS['TL_DCA']['tl_module']['palettes'][RealEstateAssetsListController::TYPE] = '{title_legend},name,headline,type;{real_estate_legend},vr_re_categories,imgSize,vr_re_grouped;{re_reader_legend},jumpTo;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; |
16 | 18 |
$GLOBALS['TL_DCA']['tl_module']['palettes'][RealEstateAssetsAdController::TYPE] = '{title_legend},name,headline,type;{real_estate_legend},vr_re_categories;{re_reader_legend},jumpTo;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; |
17 | 19 |
$GLOBALS['TL_DCA']['tl_module']['palettes'][RealEstateAssetsReaderController::TYPE] = '{title_legend},name,headline,type;{real_estate_legend},imgSize;{re_form_legend},vr_re_formUrl;{re_overview_legend},jumpTo;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; |
20 |
+$GLOBALS['TL_DCA']['tl_module']['palettes'][ManagedPropertyController::TYPE] = ' |
|
21 |
+ {title_legend},name,headline,type; |
|
22 |
+ {image_legend},imgSize; |
|
23 |
+ {re_reader_legend},jumpTo; |
|
24 |
+ {template_legend:hide},customTpl; |
|
25 |
+ {protected_legend:hide},protected; |
|
26 |
+ {expert_legend:hide},cssID |
|
27 |
+'; |
|
28 |
+ |
|
29 |
+$GLOBALS['TL_DCA']['tl_module']['palettes'][ManagedPropertyReaderController::TYPE] = ' |
|
30 |
+ {title_legend},name,headline,type; |
|
31 |
+ {image_legend},imgSize; |
|
32 |
+ {re_overview_legend},jumpTo; |
|
33 |
+ {template_legend:hide},customTpl; |
|
34 |
+ {protected_legend:hide},protected; |
|
35 |
+ {expert_legend:hide},cssID |
|
36 |
+'; |
|
18 | 37 |
|
19 | 38 |
$GLOBALS['TL_DCA']['tl_module']['fields']['vr_re_categories'] = [ |
20 | 39 |
'exclude' => true, |
21 | 40 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,184 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+declare(strict_types=1); |
|
4 |
+ |
|
5 |
+/** |
|
6 |
+ * OBG Customizations |
|
7 |
+ * |
|
8 |
+ * Copyright (c) 2021 vonRotenberg |
|
9 |
+ * |
|
10 |
+ * @license commercial |
|
11 |
+ */ |
|
12 |
+ |
|
13 |
+use Contao\DC_Table; |
|
14 |
+use Contao\DataContainer; |
|
15 |
+ |
|
16 |
+$GLOBALS['TL_DCA']['tl_vr_re_managedProperties'] = array |
|
17 |
+( |
|
18 |
+ // Config |
|
19 |
+ 'config' => array |
|
20 |
+ ( |
|
21 |
+ 'dataContainer' => DC_Table::class, |
|
22 |
+ 'enableVersioning' => true, |
|
23 |
+ 'markAsCopy' => 'address', |
|
24 |
+ 'sql' => array |
|
25 |
+ ( |
|
26 |
+ 'keys' => array |
|
27 |
+ ( |
|
28 |
+ 'id' => 'primary', |
|
29 |
+ ) |
|
30 |
+ ) |
|
31 |
+ ), |
|
32 |
+ |
|
33 |
+ // List |
|
34 |
+ 'list' => array |
|
35 |
+ ( |
|
36 |
+ 'sorting' => array |
|
37 |
+ ( |
|
38 |
+ 'mode' => DataContainer::MODE_SORTABLE, |
|
39 |
+ 'fields' => array('address'), |
|
40 |
+ 'flag' => DataContainer::SORT_INITIAL_LETTER_ASC, |
|
41 |
+ 'panelLayout' => 'filter;sort,search,limit' |
|
42 |
+ ), |
|
43 |
+ 'label' => array |
|
44 |
+ ( |
|
45 |
+ 'fields' => array('address'), |
|
46 |
+ ), |
|
47 |
+ 'global_operations' => array |
|
48 |
+ ( |
|
49 |
+ 'all' => array |
|
50 |
+ ( |
|
51 |
+ 'href' => 'act=select', |
|
52 |
+ 'class' => 'header_edit_all', |
|
53 |
+ 'attributes' => 'onclick="Backend.getScrollOffset()" accesskey="e"' |
|
54 |
+ ) |
|
55 |
+ ), |
|
56 |
+ 'operations' => array |
|
57 |
+ ( |
|
58 |
+ 'edit' => array |
|
59 |
+ ( |
|
60 |
+ 'href' => 'act=edit', |
|
61 |
+ 'icon' => 'edit.svg', |
|
62 |
+ ), |
|
63 |
+ 'copy' => array |
|
64 |
+ ( |
|
65 |
+ 'href' => 'act=copy', |
|
66 |
+ 'icon' => 'copy.svg' |
|
67 |
+ ), |
|
68 |
+ 'delete' => array |
|
69 |
+ ( |
|
70 |
+ 'href' => 'act=delete', |
|
71 |
+ 'icon' => 'delete.svg', |
|
72 |
+ 'attributes' => 'onclick="if(!confirm(\'' . ($GLOBALS['TL_LANG']['MSC']['deleteConfirm'] ?? null) . '\'))return false;Backend.getScrollOffset()"' |
|
73 |
+ ), |
|
74 |
+ 'toggle' => array( |
|
75 |
+ 'href' => 'act=toggle&field=published', |
|
76 |
+ 'icon' => 'visible.svg', |
|
77 |
+ ), |
|
78 |
+ 'show' => array |
|
79 |
+ ( |
|
80 |
+ 'href' => 'act=show', |
|
81 |
+ 'icon' => 'show.svg' |
|
82 |
+ ) |
|
83 |
+ ) |
|
84 |
+ ), |
|
85 |
+ |
|
86 |
+ // Palettes |
|
87 |
+ 'palettes' => array |
|
88 |
+ ( |
|
89 |
+ '__selector__' => array(), |
|
90 |
+ 'default' => '{data_legend},address,postal,city,gallerySRC;{description_legend},description;{map_legend},mapIframe;{publish_legend},published,start,stop', |
|
91 |
+ ), |
|
92 |
+ |
|
93 |
+ // Subpalettes |
|
94 |
+ 'subpalettes' => array |
|
95 |
+ ( |
|
96 |
+ ), |
|
97 |
+ |
|
98 |
+ // Fields |
|
99 |
+ 'fields' => array |
|
100 |
+ ( |
|
101 |
+ 'id' => array |
|
102 |
+ ( |
|
103 |
+ 'sql' => "int(10) unsigned NOT NULL auto_increment" |
|
104 |
+ ), |
|
105 |
+ 'tstamp' => array |
|
106 |
+ ( |
|
107 |
+ 'sql' => "int(10) unsigned NOT NULL default 0" |
|
108 |
+ ), |
|
109 |
+ 'description' => array |
|
110 |
+ ( |
|
111 |
+ 'exclude' => true, |
|
112 |
+ 'inputType' => 'textarea', |
|
113 |
+ 'eval' => array('mandatory'=>false, 'rte'=>'tinyMCE', 'helpwizard'=>true, 'tl_class'=>'clr'), |
|
114 |
+ 'explanation' => 'insertTags', |
|
115 |
+ 'sql' => "mediumtext NULL" |
|
116 |
+ ), |
|
117 |
+ 'postal' => array |
|
118 |
+ ( |
|
119 |
+ 'exclude' => true, |
|
120 |
+ 'inputType' => 'text', |
|
121 |
+ 'eval' => array('mandatory' => true, 'rgxp' => 'natural', 'maxlength' => 5, 'tl_class' => 'w50'), |
|
122 |
+ 'sql' => "varchar(5) NOT NULL default ''" |
|
123 |
+ ), |
|
124 |
+ 'city' => array |
|
125 |
+ ( |
|
126 |
+ 'exclude' => true, |
|
127 |
+ 'inputType' => 'text', |
|
128 |
+ 'default' => 'Kehl', |
|
129 |
+ 'eval' => array('mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50'), |
|
130 |
+ 'sql' => "varchar(255) NOT NULL default ''" |
|
131 |
+ ), |
|
132 |
+ 'address' => array |
|
133 |
+ ( |
|
134 |
+ 'exclude' => true, |
|
135 |
+ 'filter' => true, |
|
136 |
+ 'inputType' => 'text', |
|
137 |
+ 'eval' => array('mandatory' => false, 'maxlength' => 255, 'tl_class' => 'w50'), |
|
138 |
+ 'sql' => "varchar(255) NOT NULL default ''" |
|
139 |
+ ), |
|
140 |
+ 'gallerySRC' => array |
|
141 |
+ ( |
|
142 |
+ 'exclude' => true, |
|
143 |
+ 'inputType' => 'fileTree', |
|
144 |
+ 'eval' => array('mandatory' => true, 'filesOnly' => true, 'fieldType' => 'checkbox', 'multiple' => true, 'tl_class' => 'clr', 'orderField' => 'orderSRC', 'files' => true, 'extensions' => \Contao\Config::get('validImageTypes'), 'isGallery' => true), |
|
145 |
+ 'sql' => "blob NULL" |
|
146 |
+ ), |
|
147 |
+ 'orderSRC' => array |
|
148 |
+ ( |
|
149 |
+ 'label' => &$GLOBALS['TL_LANG']['MSC']['sortOrder'], |
|
150 |
+ 'sql' => "blob NULL" |
|
151 |
+ ), |
|
152 |
+ 'mapIframe' => array |
|
153 |
+ ( |
|
154 |
+ 'search' => true, |
|
155 |
+ 'inputType' => 'textarea', |
|
156 |
+ 'eval' => array('useRawRequestData'=>true, 'class'=>'monospace', 'rte'=>'ace|html', 'helpwizard'=>true), |
|
157 |
+ 'explanation' => 'insertTags', |
|
158 |
+ 'sql' => "mediumtext NULL" |
|
159 |
+ ), |
|
160 |
+ 'published' => array |
|
161 |
+ ( |
|
162 |
+ 'exclude' => true, |
|
163 |
+ 'filter' => true, |
|
164 |
+ 'toggle' => true, |
|
165 |
+ 'inputType' => 'checkbox', |
|
166 |
+ 'eval' => array('doNotCopy' => true), |
|
167 |
+ 'sql' => "char(1) NOT NULL default ''" |
|
168 |
+ ), |
|
169 |
+ 'start' => array |
|
170 |
+ ( |
|
171 |
+ 'exclude' => true, |
|
172 |
+ 'inputType' => 'text', |
|
173 |
+ 'eval' => array('rgxp' => 'datim', 'datepicker' => true, 'tl_class' => 'w50 wizard'), |
|
174 |
+ 'sql' => "varchar(10) NOT NULL default ''" |
|
175 |
+ ), |
|
176 |
+ 'stop' => array |
|
177 |
+ ( |
|
178 |
+ 'exclude' => true, |
|
179 |
+ 'inputType' => 'text', |
|
180 |
+ 'eval' => array('rgxp' => 'datim', 'datepicker' => true, 'tl_class' => 'w50 wizard'), |
|
181 |
+ 'sql' => "varchar(10) NOT NULL default ''" |
|
182 |
+ ) |
|
183 |
+ ) |
|
184 |
+); |
... | ... |
@@ -10,6 +10,12 @@ |
10 | 10 |
<trans-unit id="MOD.vr_re_categories.1"> |
11 | 11 |
<source>Immobilienobjekte verwalten</source> |
12 | 12 |
</trans-unit> |
13 |
+ <trans-unit id="MOD.managed_properties.0"> |
|
14 |
+ <source>Verwaltete Objekte</source> |
|
15 |
+ </trans-unit> |
|
16 |
+ <trans-unit id="MOD.managed_properties.1"> |
|
17 |
+ <source>Verwaltete Objekte pflegen.</source> |
|
18 |
+ </trans-unit> |
|
13 | 19 |
<trans-unit id="MOD.tl_vr_real_estate_categories"> |
14 | 20 |
<source>Objektkategorie</source> |
15 | 21 |
</trans-unit> |
16 | 22 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,96 @@ |
1 |
+<?xml version="1.0" encoding="UTF-8"?> |
|
2 |
+<xliff version="1.1"> |
|
3 |
+ <file source-language="en" target-language="de"> |
|
4 |
+ <body> |
|
5 |
+ <trans-unit id="tl_vr_re_managedProperties.address.0"> |
|
6 |
+ <source>Address</source> |
|
7 |
+ <target>Adresse</target> |
|
8 |
+ </trans-unit> |
|
9 |
+ <trans-unit id="tl_vr_re_managedProperties.address.1"> |
|
10 |
+ <source>The address of the property.</source> |
|
11 |
+ <target>Die Adresse des Objekts.</target> |
|
12 |
+ </trans-unit> |
|
13 |
+ <trans-unit id="tl_vr_re_managedProperties.postal.0"> |
|
14 |
+ <source>Postal</source> |
|
15 |
+ <target>Postleitzahl</target> |
|
16 |
+ </trans-unit> |
|
17 |
+ <trans-unit id="tl_vr_re_managedProperties.postal.1"> |
|
18 |
+ <source>The postal of the property.</source> |
|
19 |
+ <target>Die Postleitzahl des Objekts.</target> |
|
20 |
+ </trans-unit> |
|
21 |
+ <trans-unit id="tl_vr_re_managedProperties.city.0"> |
|
22 |
+ <source>City</source> |
|
23 |
+ <target>Ort</target> |
|
24 |
+ </trans-unit> |
|
25 |
+ <trans-unit id="tl_vr_re_managedProperties.city.1"> |
|
26 |
+ <source>The name of the city where the property is situated.</source> |
|
27 |
+ <target>Der Name des Ortes, wo das Objekt steht.</target> |
|
28 |
+ </trans-unit> |
|
29 |
+ <trans-unit id="tl_vr_re_managedProperties.gallerySRC.0"> |
|
30 |
+ <source>Images</source> |
|
31 |
+ <target>Bilder</target> |
|
32 |
+ </trans-unit> |
|
33 |
+ <trans-unit id="tl_vr_re_managedProperties.gallerySRC.1"> |
|
34 |
+ <source>Select related images of the property in the file browser.</source> |
|
35 |
+ <target>Wählen Sie relevante Bilder zum Objekt aus dem Dateibrowser aus.</target> |
|
36 |
+ </trans-unit> |
|
37 |
+ <trans-unit id="tl_vr_re_managedProperties.description.0"> |
|
38 |
+ <source>Description</source> |
|
39 |
+ <target>Beschreibung</target> |
|
40 |
+ </trans-unit> |
|
41 |
+ <trans-unit id="tl_vr_re_managedProperties.description.1"> |
|
42 |
+ <source>A describing text about the property.</source> |
|
43 |
+ <target>Ein beschreibender Text zum Objekt.</target> |
|
44 |
+ </trans-unit> |
|
45 |
+ <trans-unit id="tl_vr_re_managedProperties.mapIframe.0"> |
|
46 |
+ <source>Map HTML</source> |
|
47 |
+ <target>Karten-HTML</target> |
|
48 |
+ </trans-unit> |
|
49 |
+ <trans-unit id="tl_vr_re_managedProperties.mapIframe.1"> |
|
50 |
+ <source>HTML snippet for the map to embed.</source> |
|
51 |
+ <target>HTML-Snippet für die einzubettende Karte.</target> |
|
52 |
+ </trans-unit> |
|
53 |
+ <trans-unit id="tl_vr_re_managedProperties.published.0"> |
|
54 |
+ <source>Publish</source> |
|
55 |
+ <target>Veröffentlichen</target> |
|
56 |
+ </trans-unit> |
|
57 |
+ <trans-unit id="tl_vr_re_managedProperties.published.1"> |
|
58 |
+ <source>The property is published on the website.</source> |
|
59 |
+ <target>Das Objekt wird auf der Webseite veröffentlicht.</target> |
|
60 |
+ </trans-unit> |
|
61 |
+ <trans-unit id="tl_vr_re_managedProperties.start.0"> |
|
62 |
+ <source>Publish from</source> |
|
63 |
+ <target>Anzeigen ab</target> |
|
64 |
+ </trans-unit> |
|
65 |
+ <trans-unit id="tl_vr_re_managedProperties.start.1"> |
|
66 |
+ <source>From when the object should be visible. Leave empty for immediate publication.</source> |
|
67 |
+ <target>Ab wann das Objekt sichtbar sein soll. Leer lassen für sofortige Veröffentlichung.</target> |
|
68 |
+ </trans-unit> |
|
69 |
+ <trans-unit id="tl_vr_re_managedProperties.stop.0"> |
|
70 |
+ <source>Publish until</source> |
|
71 |
+ <target>Anzeigen bis</target> |
|
72 |
+ </trans-unit> |
|
73 |
+ <trans-unit id="tl_vr_re_managedProperties.stop.1"> |
|
74 |
+ <source>Until when the object should be visible. Leave empty for permanent publication.</source> |
|
75 |
+ <target>Bis wann das Objekt sichtbar sein soll. Leer lassen für dauerhafte Veröffentlichung.</target> |
|
76 |
+ </trans-unit> |
|
77 |
+ |
|
78 |
+ <trans-unit id="tl_vr_re_managedProperties.data_legend"> |
|
79 |
+ <source>Basic data</source> |
|
80 |
+ <target>Grunddaten</target> |
|
81 |
+ </trans-unit> |
|
82 |
+ <trans-unit id="tl_vr_re_managedProperties.description_legend"> |
|
83 |
+ <source>Description</source> |
|
84 |
+ <target>Beschreibung</target> |
|
85 |
+ </trans-unit> |
|
86 |
+ <trans-unit id="tl_vr_re_managedProperties.map_legend"> |
|
87 |
+ <source>Map</source> |
|
88 |
+ <target>Karte</target> |
|
89 |
+ </trans-unit> |
|
90 |
+ <trans-unit id="tl_vr_re_managedProperties.publish_legend"> |
|
91 |
+ <source>Publishing settings</source> |
|
92 |
+ <target>Veröffentlichungs-Einstellungen</target> |
|
93 |
+ </trans-unit> |
|
94 |
+ </body> |
|
95 |
+ </file> |
|
96 |
+</xliff> |
|
0 | 97 |
\ No newline at end of file |
1 | 98 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,72 @@ |
1 |
+{% extends '@Contao/frontend_module/_base.html.twig' %} |
|
2 |
+{% import "@ContaoCore/Image/Studio/_macros.html.twig" as studio %} |
|
3 |
+ |
|
4 |
+{% block content %} |
|
5 |
+ |
|
6 |
+ {% block filter %} |
|
7 |
+ <div class="-padding content-background-wrapper"> |
|
8 |
+ <div class="content-background-wrapper-bg"> |
|
9 |
+ </div> |
|
10 |
+ |
|
11 |
+ <div class="content-background-wrapper-fg"> |
|
12 |
+ <div class="content-grid"> |
|
13 |
+ <div class="fragments"> |
|
14 |
+ <h5>{{ 'MSC.re_filter'|trans({}, 'contao_default') }}</h5> |
|
15 |
+ <form class="assets-list-filter" hx-get="{{ pageUrl is defined ? pageUrl : '' }}" hx-push-url="false" hx-headers='{"VR-Ajax": "RePropertiesList"}' hx-trigger="change, submit" hx-target="closest .module-managed-property" hx-indicator="body" class="filter"> |
|
16 |
+ {% if filterOptions is defined and filterOptions is iterable %} |
|
17 |
+ {% for key, options in filterOptions %} |
|
18 |
+ <div class="filter-wrapper"> |
|
19 |
+ <select name="filter[{{ key }}]"{% if filter[key] is defined and filter[key] is not empty %} class="active"{% endif %}> |
|
20 |
+ <option value="">{{ ('REF.re_filter.' ~ key)|trans({}, 'contao_default') }}</option> |
|
21 |
+ {% for value, label in options %} |
|
22 |
+ <option value="{{ value }}"{% if filter[key] is defined and filter[key] == value %} selected{% endif %}>{{ label }}</option> |
|
23 |
+ {% endfor %} |
|
24 |
+ </select> |
|
25 |
+ </div> |
|
26 |
+ {% endfor %} |
|
27 |
+ {% endif %} |
|
28 |
+ </form> |
|
29 |
+ </div> |
|
30 |
+ </div> |
|
31 |
+ </div> |
|
32 |
+ </div> |
|
33 |
+ {% endblock %} |
|
34 |
+ |
|
35 |
+ {% block assets %} |
|
36 |
+ <div class="assetList"> |
|
37 |
+ {% for item in assets %} |
|
38 |
+ {% block item %} |
|
39 |
+ <div class="asset re_asset_card"> |
|
40 |
+ {% if item.teaserFigure %} |
|
41 |
+ {{- studio.figure(item.teaserFigure, { attr: { class: ('image_container media') }}) -}} |
|
42 |
+ {% endif %} |
|
43 |
+ |
|
44 |
+ <div class="details"> |
|
45 |
+ <ul> |
|
46 |
+ <li> |
|
47 |
+ <span class="label">Adresse:</span> |
|
48 |
+ {% if item.address is not empty %}{{ item.address }}<br>{% endif %} |
|
49 |
+ {% if item.postal is not empty and item.city is not empty %}{{ item.postal }} {{ item.city }}<br>{% endif %} |
|
50 |
+ </li> |
|
51 |
+ {% if item.livingSpace > 0 %} |
|
52 |
+ <li> |
|
53 |
+ <span class="label">Wohnfläche:</span> |
|
54 |
+ {{ item.livingSpace|number_format(2, ',', '') }} m² |
|
55 |
+ </li> |
|
56 |
+ {% endif %} |
|
57 |
+ </ul> |
|
58 |
+ {% if item.detailsUrl %} |
|
59 |
+ <p class="details-link"><a class="link" href="{{ item.detailsUrl }}">{{ 'MSC.more'|trans({}, 'contao_default') }}</a></p> |
|
60 |
+ {% endif %} |
|
61 |
+ </div> |
|
62 |
+ </div> |
|
63 |
+ {% endblock %} |
|
64 |
+ {% endfor %} |
|
65 |
+ </div> |
|
66 |
+ {% endblock %} |
|
67 |
+ |
|
68 |
+ |
|
69 |
+ {% block overlay %} |
|
70 |
+ <div class="assets-list-overlay"></div> |
|
71 |
+ {% endblock %} |
|
72 |
+{% endblock %} |
0 | 73 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,75 @@ |
1 |
+{% extends '@Contao/frontend_module/_base.html.twig' %} |
|
2 |
+{% use "@Contao/component/_list.html.twig" %} |
|
3 |
+{% use "@Contao/component/_figure.html.twig" %} |
|
4 |
+ |
|
5 |
+{%- macro listEntry(label, value, options = {}) -%} |
|
6 |
+ {%- set class = options.class|default({}) -%} |
|
7 |
+ {%- set prepend = options.prepend|default({}) %} |
|
8 |
+ {% set append = options.append|default({}) -%} |
|
9 |
+ {% set strong = options.strong is defined and options.strong ? true : false %} |
|
10 |
+ {% apply spaceless %} |
|
11 |
+ {% if label and value %} |
|
12 |
+ <li class="{% if class %}{{- class -}}{% endif %}{{- strong ? ' strong' : '' -}}"> |
|
13 |
+ <span class="label">{{- label -}}</span> |
|
14 |
+ <span class="value">{% if prepend %}{{ prepend }}{% endif %}{{- value -}}{% if append %}{{ append }}{% endif %}</span> |
|
15 |
+ </li> |
|
16 |
+ {% endif %} |
|
17 |
+ {% endapply %} |
|
18 |
+{%- endmacro -%} |
|
19 |
+{%- macro backgroundWrapper_open(classes = '') -%} |
|
20 |
+<div class="{{ classes ? classes ~ ' ' : '' }}content-background-wrapper"> |
|
21 |
+ <div class="content-background-wrapper-bg"> |
|
22 |
+ </div> |
|
23 |
+ <div class="content-background-wrapper-fg"> |
|
24 |
+ <div class="content-grid"> |
|
25 |
+ <div class="fragments"> |
|
26 |
+ {%- endmacro -%} |
|
27 |
+ {%- macro backgroundWrapper_close() -%} |
|
28 |
+ </div> |
|
29 |
+ </div> |
|
30 |
+ </div> |
|
31 |
+</div> |
|
32 |
+{%- endmacro -%} |
|
33 |
+ |
|
34 |
+ |
|
35 |
+{% block content %} |
|
36 |
+ {% import "@ContaoCore/Image/Studio/_macros.html.twig" as studio %} |
|
37 |
+ |
|
38 |
+ <div class="re_asset_expose"> |
|
39 |
+ |
|
40 |
+ {{ _self.backgroundWrapper_open('-padding-medium') }} |
|
41 |
+ <p class="overviewLink"><a class="btn btn-outline-primary" href="{{ item.listUrl }}">Zurück zur Übersicht</a></p> |
|
42 |
+ <h1>{% if item.city %}{{ item.city }}{% endif %}{% if item.address %} {{ item.address }}{% endif %}</h1> |
|
43 |
+ {{ _self.backgroundWrapper_close }} |
|
44 |
+ |
|
45 |
+ {{ _self.backgroundWrapper_open('-alt-color-1 -padding-medium') }} |
|
46 |
+ |
|
47 |
+ <div class="teaser-wrapper"> |
|
48 |
+ {% if item.teaserFigure %} |
|
49 |
+ {{- studio.figure(item.teaserFigure, { attr: { class: ('image_container media') }}) -}} |
|
50 |
+ {% endif %} |
|
51 |
+ {% if item.map %} |
|
52 |
+ {% block map %}<div class="map-embed">{{ item.map|default|insert_tag|raw }}</div>{% endblock %} |
|
53 |
+ {% endif %} |
|
54 |
+ </div> |
|
55 |
+ |
|
56 |
+ {% if item.description %} |
|
57 |
+ <div class="description">{{ item.description|raw }}</div> |
|
58 |
+ {% endif %} |
|
59 |
+ |
|
60 |
+ <div class="expose-gallery"> |
|
61 |
+ {% with {items: item.galleryFigures} %}{{ block('list_component') }}{% endwith %} |
|
62 |
+ </div> |
|
63 |
+ {{ _self.backgroundWrapper_close }} |
|
64 |
+ |
|
65 |
+ {{ _self.backgroundWrapper_open('-padding') }} |
|
66 |
+ <p class="overviewLink"><a class="btn btn-outline-primary" href="{{ item.listUrl }}">Zurück zur Übersicht</a></p> |
|
67 |
+ {{ _self.backgroundWrapper_close }} |
|
68 |
+ |
|
69 |
+ |
|
70 |
+ </div> |
|
71 |
+{% endblock %} |
|
72 |
+ |
|
73 |
+{% block list_item %} |
|
74 |
+ {% with {figure: item} %}{{ block('figure_component') }}{% endwith %} |
|
75 |
+{% endblock %} |
0 | 76 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,217 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+declare(strict_types=1); |
|
4 |
+ |
|
5 |
+namespace vonRotenberg\RealEstateListingBundle\Controller\FrontendModule; |
|
6 |
+ |
|
7 |
+use vonRotenberg\RealEstateListingBundle\Model\ManagedPropertyModel; |
|
8 |
+use Contao\ArrayUtil; |
|
9 |
+use Contao\CoreBundle\Controller\FrontendModule\AbstractFrontendModuleController; |
|
10 |
+use Contao\CoreBundle\DependencyInjection\Attribute\AsFrontendModule; |
|
11 |
+use Contao\CoreBundle\Exception\ResponseException; |
|
12 |
+use Contao\CoreBundle\Image\Studio\Figure; |
|
13 |
+use Contao\CoreBundle\Image\Studio\FigureBuilder; |
|
14 |
+use Contao\CoreBundle\Twig\FragmentTemplate; |
|
15 |
+use Contao\File; |
|
16 |
+use Contao\FilesModel; |
|
17 |
+use Contao\Input; |
|
18 |
+use Contao\ModuleModel; |
|
19 |
+use Contao\PageModel; |
|
20 |
+use Contao\StringUtil; |
|
21 |
+use Contao\System; |
|
22 |
+use Symfony\Component\HttpFoundation\Request; |
|
23 |
+use Symfony\Component\HttpFoundation\Response; |
|
24 |
+ |
|
25 |
+#[AsFrontendModule(category: 'vr_real_estate')] |
|
26 |
+class ManagedPropertyController extends AbstractFrontendModuleController |
|
27 |
+{ |
|
28 |
+ public const TYPE = 'managed_property'; |
|
29 |
+ protected function getResponse(FragmentTemplate $template, ModuleModel $model, Request $request): Response |
|
30 |
+ { |
|
31 |
+ |
|
32 |
+ $arrAssets = []; |
|
33 |
+ $arrFilterOptions = [ |
|
34 |
+ 'city' => [] |
|
35 |
+ ]; |
|
36 |
+ $arrFilterSelected = []; |
|
37 |
+ $arrAssetsOptions = []; |
|
38 |
+ |
|
39 |
+ $jumpTo = PageModel::findByPk($model->jumpTo); |
|
40 |
+ $urlGenerator = System::getContainer()->get('contao.routing.content_url_generator'); |
|
41 |
+ |
|
42 |
+ // Filter |
|
43 |
+ if (isset($_GET['filter']) && \is_array(Input::get('filter'))) |
|
44 |
+ { |
|
45 |
+ foreach (Input::get('filter') as $filter=>$value) |
|
46 |
+ { |
|
47 |
+ if (in_array($filter, array_keys($arrFilterOptions)) && !empty($value)) |
|
48 |
+ { |
|
49 |
+ $rawValue = StringUtil::decodeEntities($value); |
|
50 |
+ $arrFilterSelected[$filter] = $rawValue; |
|
51 |
+ |
|
52 |
+ if (preg_match('/^.*<>.*$/',$rawValue)) |
|
53 |
+ { |
|
54 |
+ list($start,$stop) = preg_split('/<>/',$rawValue, 2); |
|
55 |
+ $arrAssetsOptions['column'][$filter] = "$filter BETWEEN $start AND $stop"; |
|
56 |
+ } else { |
|
57 |
+ $arrAssetsOptions['column'][$filter] = "$filter = ?"; |
|
58 |
+ $arrAssetsOptions['value'][$filter] = $rawValue; |
|
59 |
+ } |
|
60 |
+ } |
|
61 |
+ } |
|
62 |
+ } |
|
63 |
+ |
|
64 |
+ if (($assets = ManagedPropertyModel::findAllPublished(0,0,$arrAssetsOptions)) === null) |
|
65 |
+ { |
|
66 |
+ return $template->getResponse(); |
|
67 |
+ } |
|
68 |
+ |
|
69 |
+ // Figure Builder |
|
70 |
+ $figureBuilder = System::getContainer() |
|
71 |
+ ->get('contao.image.studio') |
|
72 |
+ ->createFigureBuilder() |
|
73 |
+ ->setSize($model->imgSize) |
|
74 |
+ ->setLightboxGroupIdentifier('lb' . $model->id); |
|
75 |
+ |
|
76 |
+ foreach ($assets as $asset) |
|
77 |
+ { |
|
78 |
+ $arrItem = array_merge($asset->row(), [ |
|
79 |
+ 'teaserFigure' => $this->getImageFigures($asset->gallerySRC, $figureBuilder, $asset->orderSRC, 1), |
|
80 |
+ 'detailsUrl' => $jumpTo !== null ? $urlGenerator->generate($jumpTo, ['parameters'=>'/items/'.$asset->id]) : null |
|
81 |
+ ]); |
|
82 |
+ |
|
83 |
+ $arrAssets[] = $arrItem; |
|
84 |
+ } |
|
85 |
+ |
|
86 |
+ // Populate filters |
|
87 |
+ $filterAssets = ManagedPropertyModel::findAllPublished(); |
|
88 |
+ foreach ($filterAssets as $asset) |
|
89 |
+ { |
|
90 |
+ // Filter options |
|
91 |
+ if (!empty($asset->city)) |
|
92 |
+ { |
|
93 |
+ $tmpOptions = $arrAssetsOptions; |
|
94 |
+ $tmpOptions['column'] = array_merge((isset($arrAssetsOptions['column']) ? $arrAssetsOptions['column'] : []),['city'=>'city = ?']); |
|
95 |
+ $tmpOptions['value'] = array_merge((isset($arrAssetsOptions['value']) ? $arrAssetsOptions['value'] : []),['city'=>$asset->city]); |
|
96 |
+ $count = ManagedPropertyModel::countAllPublished($tmpOptions); |
|
97 |
+ $arrFilterOptions['city'][$asset->city] = $asset->city . ' ('.$count.')'; |
|
98 |
+ } |
|
99 |
+ } |
|
100 |
+ |
|
101 |
+ foreach (array_keys($arrFilterOptions) as $filterName) |
|
102 |
+ { |
|
103 |
+ $arrFilterOptions[$filterName] = array_unique($arrFilterOptions[$filterName]); |
|
104 |
+ } |
|
105 |
+ |
|
106 |
+ // Set template data |
|
107 |
+ $template->set('filterOptions',$arrFilterOptions); |
|
108 |
+ $template->set('filter',$arrFilterSelected); |
|
109 |
+ $template->set('assets',$arrAssets); |
|
110 |
+ |
|
111 |
+ // Handle ajax |
|
112 |
+ if ($request->headers->get('VR-Ajax') == 'RePropertiesList') |
|
113 |
+ { |
|
114 |
+ throw new ResponseException($template->getResponse()); |
|
115 |
+ } |
|
116 |
+ |
|
117 |
+ return $template->getResponse(); |
|
118 |
+ } |
|
119 |
+ |
|
120 |
+ /** |
|
121 |
+ * @param string|array $strUuids |
|
122 |
+ * @param FigureBuilder $figureBuilder |
|
123 |
+ * @param string|array $strOrder |
|
124 |
+ * |
|
125 |
+ * @return array|Figure |
|
126 |
+ * @throws \Exception |
|
127 |
+ */ |
|
128 |
+ public function getImageFigures($strUuids, $figureBuilder, $strOrder = null, int $intLimit = 0, int $intOffset = 0) |
|
129 |
+ { |
|
130 |
+ $arrImageFigures = []; |
|
131 |
+ |
|
132 |
+ if (($imageFiles = FilesModel::findMultipleByUuids(StringUtil::deserialize($strUuids))) !== null) |
|
133 |
+ { |
|
134 |
+ $images = array(); |
|
135 |
+ while ($imageFiles->next()) |
|
136 |
+ { |
|
137 |
+ // Continue if the files has been processed or does not exist |
|
138 |
+ if (isset($images[$imageFiles->path]) || !file_exists(System::getContainer()->getParameter('kernel.project_dir') . '/' . $imageFiles->path)) |
|
139 |
+ { |
|
140 |
+ continue; |
|
141 |
+ } |
|
142 |
+ |
|
143 |
+ // Single files |
|
144 |
+ if ($imageFiles->type == 'file') |
|
145 |
+ { |
|
146 |
+ $objFile = new File($imageFiles->path); |
|
147 |
+ |
|
148 |
+ if (!$objFile->isImage) |
|
149 |
+ { |
|
150 |
+ continue; |
|
151 |
+ } |
|
152 |
+ |
|
153 |
+ // Add the image |
|
154 |
+ $images[$imageFiles->path] = $imageFiles->current(); |
|
155 |
+ } // Folders |
|
156 |
+ else |
|
157 |
+ { |
|
158 |
+ $objSubfiles = FilesModel::findByPid($imageFiles->uuid, array('order' => 'name')); |
|
159 |
+ |
|
160 |
+ if ($objSubfiles === null) |
|
161 |
+ { |
|
162 |
+ continue; |
|
163 |
+ } |
|
164 |
+ |
|
165 |
+ while ($objSubfiles->next()) |
|
166 |
+ { |
|
167 |
+ // Skip subfolders |
|
168 |
+ if ($objSubfiles->type == 'folder') |
|
169 |
+ { |
|
170 |
+ continue; |
|
171 |
+ } |
|
172 |
+ |
|
173 |
+ $objFile = new File($objSubfiles->path); |
|
174 |
+ |
|
175 |
+ if (!$objFile->isImage) |
|
176 |
+ { |
|
177 |
+ continue; |
|
178 |
+ } |
|
179 |
+ |
|
180 |
+ // Add the image |
|
181 |
+ $images[$objSubfiles->path] = $objSubfiles->current(); |
|
182 |
+ } |
|
183 |
+ } |
|
184 |
+ } |
|
185 |
+ |
|
186 |
+ if ($strOrder !== null) |
|
187 |
+ { |
|
188 |
+ $images = ArrayUtil::sortByOrderField($images, $strOrder); |
|
189 |
+ } |
|
190 |
+ $images = array_values($images); |
|
191 |
+ |
|
192 |
+ // Offset images |
|
193 |
+ if ($intOffset > 0) |
|
194 |
+ { |
|
195 |
+ $images = \array_slice($images, ($intOffset < count($images) ? $intOffset : count($images))); |
|
196 |
+ } |
|
197 |
+ |
|
198 |
+ // Limit number of images |
|
199 |
+ if ($intLimit > 0) |
|
200 |
+ { |
|
201 |
+ $images = \array_slice($images, 0, $intLimit); |
|
202 |
+ } |
|
203 |
+ |
|
204 |
+ // Build figures of images |
|
205 |
+ foreach ($images as $image) |
|
206 |
+ { |
|
207 |
+ $figure = $figureBuilder |
|
208 |
+ ->fromFilesModel($image) |
|
209 |
+ ->build(); |
|
210 |
+ |
|
211 |
+ $arrImageFigures[] = $figure; |
|
212 |
+ } |
|
213 |
+ |
|
214 |
+ } |
|
215 |
+ return count ($arrImageFigures) === 1 && $intLimit === 1 ? array_shift($arrImageFigures) : $arrImageFigures; |
|
216 |
+ } |
|
217 |
+} |
0 | 218 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,187 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+declare(strict_types=1); |
|
4 |
+ |
|
5 |
+namespace vonRotenberg\RealEstateListingBundle\Controller\FrontendModule; |
|
6 |
+ |
|
7 |
+use vonRotenberg\RealEstateListingBundle\Model\ManagedPropertyModel; |
|
8 |
+use Contao\ArrayUtil; |
|
9 |
+use Contao\Controller; |
|
10 |
+use Contao\CoreBundle\Controller\FrontendModule\AbstractFrontendModuleController; |
|
11 |
+use Contao\CoreBundle\DependencyInjection\Attribute\AsFrontendModule; |
|
12 |
+use Contao\CoreBundle\Exception\ResponseException; |
|
13 |
+use Contao\CoreBundle\Image\Studio\Figure; |
|
14 |
+use Contao\CoreBundle\Image\Studio\FigureBuilder; |
|
15 |
+use Contao\CoreBundle\Twig\FragmentTemplate; |
|
16 |
+use Contao\Date; |
|
17 |
+use Contao\File; |
|
18 |
+use Contao\FilesModel; |
|
19 |
+use Contao\FrontendTemplate; |
|
20 |
+use Contao\Input; |
|
21 |
+use Contao\ModuleModel; |
|
22 |
+use Contao\PageModel; |
|
23 |
+use Contao\StringUtil; |
|
24 |
+use Contao\System; |
|
25 |
+use Contao\Template; |
|
26 |
+use Symfony\Component\HttpFoundation\Request; |
|
27 |
+use Symfony\Component\HttpFoundation\Response; |
|
28 |
+use Symfony\Contracts\Translation\TranslatorInterface; |
|
29 |
+use vonRotenberg\RealEstateListingBundle\Model\RealEstateAssetsModel; |
|
30 |
+ |
|
31 |
+#[AsFrontendModule(category: 'vr_real_estate')] |
|
32 |
+class ManagedPropertyReaderController extends AbstractFrontendModuleController |
|
33 |
+{ |
|
34 |
+ public const TYPE = 'managed_property_reader'; |
|
35 |
+ /** |
|
36 |
+ * @var RealEstateAssetsModel|null |
|
37 |
+ */ |
|
38 |
+ protected $asset; |
|
39 |
+ |
|
40 |
+ /** |
|
41 |
+ * @var TranslatorInterface |
|
42 |
+ */ |
|
43 |
+ protected $translator; |
|
44 |
+ |
|
45 |
+ protected function getResponse(FragmentTemplate $template, ModuleModel $model, Request $request): Response |
|
46 |
+ { |
|
47 |
+ $this->translator = System::getContainer()->get('translator'); |
|
48 |
+ Controller::loadLanguageFile(ManagedPropertyModel::getTable()); |
|
49 |
+ |
|
50 |
+ $jumpTo = PageModel::findByPk($model->jumpTo); |
|
51 |
+ |
|
52 |
+ // Set the item from the auto_item parameter |
|
53 |
+ if (!isset($_GET['items']) && \Config::get('useAutoItem') && isset($_GET['auto_item'])) |
|
54 |
+ { |
|
55 |
+ Input::setGet('items', Input::get('auto_item')); |
|
56 |
+ } |
|
57 |
+ |
|
58 |
+ $this->asset = ManagedPropertyModel::findPublishedByIdOrAlias(Input::get('items')); |
|
59 |
+ |
|
60 |
+ if ($this->asset === null) |
|
61 |
+ { |
|
62 |
+ return new Response(); |
|
63 |
+ } |
|
64 |
+ |
|
65 |
+ $figureBuilder = System::getContainer() |
|
66 |
+ ->get('contao.image.studio') |
|
67 |
+ ->createFigureBuilder() |
|
68 |
+ ->setSize($model->imgSize) |
|
69 |
+ ->enableLightbox(true); |
|
70 |
+// ->setLightboxGroupIdentifier('lb' . $model->id); |
|
71 |
+ |
|
72 |
+ $arrItem = array_merge($this->asset->row(), [ |
|
73 |
+ 'features' => StringUtil::deserialize($this->asset->features,true), |
|
74 |
+ 'availableFrom' => ($this->asset->availability == 'immediately' ? $this->translator->trans('REF.re_availability.immediately', [], 'contao_default') : Date::parse(Date::getNumericDateFormat(), $this->asset->availableFrom)), |
|
75 |
+ 'deadline' => ($this->asset->stop > 0 ? Date::parse(Date::getNumericDateFormat(), $this->asset->stop) : ''), |
|
76 |
+ 'teaserFigure' => $this->getImageFigures($this->asset->gallerySRC, $figureBuilder, $this->asset->orderSRC, 1), |
|
77 |
+ 'galleryFigures' => $this->getImageFigures($this->asset->gallerySRC, $figureBuilder, $this->asset->orderSRC, 0, 0), |
|
78 |
+ 'floorPlansFigures' => $this->getImageFigures($this->asset->floorPlansSRC, $figureBuilder, $this->asset->floorPlansOrderSRC), |
|
79 |
+ 'listUrl' => $jumpTo !== null ? $jumpTo->getFrontendUrl() : null, |
|
80 |
+ 'pdfUrl' => $request->getBaseUrl() . $request->getPathInfo() . '?pdf', |
|
81 |
+ 'qrUrl' => $request->getUriForPath($request->getPathInfo()), |
|
82 |
+ 'map' => $this->asset->mapIframe ?? '' |
|
83 |
+ ]); |
|
84 |
+ |
|
85 |
+ $template->item = $arrItem; |
|
86 |
+ |
|
87 |
+ return $template->getResponse(); |
|
88 |
+ } |
|
89 |
+ |
|
90 |
+ /** |
|
91 |
+ * @param string|array $strUuids |
|
92 |
+ * @param FigureBuilder $figureBuilder |
|
93 |
+ * @param string|array $strOrder |
|
94 |
+ * |
|
95 |
+ * @return array|Figure |
|
96 |
+ * @throws \Exception |
|
97 |
+ */ |
|
98 |
+ public function getImageFigures($strUuids, $figureBuilder, $strOrder = null, int $intLimit = 0, int $intOffset = 0) |
|
99 |
+ { |
|
100 |
+ $arrImageFigures = []; |
|
101 |
+ |
|
102 |
+ if (($imageFiles = FilesModel::findMultipleByUuids(StringUtil::deserialize($strUuids))) !== null) |
|
103 |
+ { |
|
104 |
+ $images = array(); |
|
105 |
+ while ($imageFiles->next()) |
|
106 |
+ { |
|
107 |
+ // Continue if the files has been processed or does not exist |
|
108 |
+ if (isset($images[$imageFiles->path]) || !file_exists(System::getContainer()->getParameter('kernel.project_dir') . '/' . $imageFiles->path)) |
|
109 |
+ { |
|
110 |
+ continue; |
|
111 |
+ } |
|
112 |
+ |
|
113 |
+ // Single files |
|
114 |
+ if ($imageFiles->type == 'file') |
|
115 |
+ { |
|
116 |
+ $objFile = new File($imageFiles->path); |
|
117 |
+ |
|
118 |
+ if (!$objFile->isImage) |
|
119 |
+ { |
|
120 |
+ continue; |
|
121 |
+ } |
|
122 |
+ |
|
123 |
+ // Add the image |
|
124 |
+ $images[$imageFiles->path] = $imageFiles->current(); |
|
125 |
+ } // Folders |
|
126 |
+ else |
|
127 |
+ { |
|
128 |
+ $objSubfiles = FilesModel::findByPid($imageFiles->uuid, array('order' => 'name')); |
|
129 |
+ |
|
130 |
+ if ($objSubfiles === null) |
|
131 |
+ { |
|
132 |
+ continue; |
|
133 |
+ } |
|
134 |
+ |
|
135 |
+ while ($objSubfiles->next()) |
|
136 |
+ { |
|
137 |
+ // Skip subfolders |
|
138 |
+ if ($objSubfiles->type == 'folder') |
|
139 |
+ { |
|
140 |
+ continue; |
|
141 |
+ } |
|
142 |
+ |
|
143 |
+ $objFile = new File($objSubfiles->path); |
|
144 |
+ |
|
145 |
+ if (!$objFile->isImage) |
|
146 |
+ { |
|
147 |
+ continue; |
|
148 |
+ } |
|
149 |
+ |
|
150 |
+ // Add the image |
|
151 |
+ $images[$objSubfiles->path] = $objSubfiles->current(); |
|
152 |
+ } |
|
153 |
+ } |
|
154 |
+ } |
|
155 |
+ |
|
156 |
+ if ($strOrder !== null) |
|
157 |
+ { |
|
158 |
+ $images = ArrayUtil::sortByOrderField($images, $strOrder); |
|
159 |
+ } |
|
160 |
+ $images = array_values($images); |
|
161 |
+ |
|
162 |
+ // Offset images |
|
163 |
+ if ($intOffset > 0) |
|
164 |
+ { |
|
165 |
+ $images = \array_slice($images, ($intOffset < count($images) ? $intOffset : count($images))); |
|
166 |
+ } |
|
167 |
+ |
|
168 |
+ // Limit number of images |
|
169 |
+ if ($intLimit > 0) |
|
170 |
+ { |
|
171 |
+ $images = \array_slice($images, 0, $intLimit); |
|
172 |
+ } |
|
173 |
+ |
|
174 |
+ // Build figures of images |
|
175 |
+ foreach ($images as $image) |
|
176 |
+ { |
|
177 |
+ $figure = $figureBuilder |
|
178 |
+ ->fromFilesModel($image) |
|
179 |
+ ->build(); |
|
180 |
+ |
|
181 |
+ $arrImageFigures[] = $figure; |
|
182 |
+ } |
|
183 |
+ |
|
184 |
+ } |
|
185 |
+ return count ($arrImageFigures) === 1 && $intLimit === 1 ? array_shift($arrImageFigures) : $arrImageFigures; |
|
186 |
+ } |
|
187 |
+} |
0 | 188 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,178 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+/** |
|
4 |
+ * OBG Customizations |
|
5 |
+ * |
|
6 |
+ * Copyright (c) 2021 vonRotenberg |
|
7 |
+ * |
|
8 |
+ * @license commercial |
|
9 |
+ */ |
|
10 |
+ |
|
11 |
+namespace vonRotenberg\RealEstateListingBundle\Model; |
|
12 |
+ |
|
13 |
+use Contao\Date; |
|
14 |
+use Contao\Model; |
|
15 |
+use Contao\Model\Collection; |
|
16 |
+ |
|
17 |
+/** |
|
18 |
+ * Reads and writes assets |
|
19 |
+ * |
|
20 |
+ * @property string|integer $id |
|
21 |
+ * @property string|integer $tstamp |
|
22 |
+ * @property string $address |
|
23 |
+ * @property string $postal |
|
24 |
+ * @property string $city |
|
25 |
+ * @property string|null $gallerySRC |
|
26 |
+ * @property string|null $orderSRC |
|
27 |
+ * @property string|null $description |
|
28 |
+ * @property string|boolean $published |
|
29 |
+ * @property string|integer $start |
|
30 |
+ * @property string|integer $stop |
|
31 |
+ * |
|
32 |
+ * @method static ManagedPropertyModel|null findById($id, array $opt = array()) |
|
33 |
+ * @method static ManagedPropertyModel|null findByPk($id, array $opt = array()) |
|
34 |
+ * @method static ManagedPropertyModel|null findOneBy($col, $val, array $opt = array()) |
|
35 |
+ * @method static ManagedPropertyModel|null findOneByTstamp($val, array $opt = array()) |
|
36 |
+ * @method static ManagedPropertyModel|null findOneByAddress($val, array $opt = array()) |
|
37 |
+ * @method static ManagedPropertyModel|null findOneByPostal($val, array $opt = array()) |
|
38 |
+ * @method static ManagedPropertyModel|null findOneByCity($val, array $opt = array()) |
|
39 |
+ * @method static ManagedPropertyModel|null findOneByGallerySRC($val, array $opt = array()) |
|
40 |
+ * @method static ManagedPropertyModel|null findOneByDescription($val, array $opt = array()) |
|
41 |
+ * @method static ManagedPropertyModel|null findOneByPublished($val, array $opt = array()) |
|
42 |
+ * @method static ManagedPropertyModel|null findOneByStart($val, array $opt = array()) |
|
43 |
+ * @method static ManagedPropertyModel|null findOneByStop($val, array $opt = array()) |
|
44 |
+ * |
|
45 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByTstamp($val, array $opt = array()) |
|
46 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByAddress($val, array $opt = array()) |
|
47 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByPostal($val, array $opt = array()) |
|
48 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByCity($val, array $opt = array()) |
|
49 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByGallerySRC($val, array $opt = array()) |
|
50 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByDescription($val, array $opt = array()) |
|
51 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByPublished($val, array $opt = array()) |
|
52 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByStart($val, array $opt = array()) |
|
53 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findByStop($val, array $opt = array()) |
|
54 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findMultipleByIds($val, array $opt = array()) |
|
55 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findBy($col, $val, array $opt = array()) |
|
56 |
+ * @method static Collection|ManagedPropertyModel[]|ManagedPropertyModel|null findAll(array $opt = array()) |
|
57 |
+ * |
|
58 |
+ * @method static integer countById($id, array $opt = array()) |
|
59 |
+ * @method static integer countByTstamp($val, array $opt = array()) |
|
60 |
+ * @method static integer countByAddress($val, array $opt = array()) |
|
61 |
+ * @method static integer countByPostal($val, array $opt = array()) |
|
62 |
+ * @method static integer countByCity($val, array $opt = array()) |
|
63 |
+ * @method static integer countByGallerySRC($val, array $opt = array()) |
|
64 |
+ * @method static integer countByDescription($val, array $opt = array()) |
|
65 |
+ * @method static integer countByPublished($val, array $opt = array()) |
|
66 |
+ * @method static integer countByStart($val, array $opt = array()) |
|
67 |
+ * @method static integer countByStop($val, array $opt = array()) |
|
68 |
+ * |
|
69 |
+ * @author Benjamin Roth <https://www.vonrotenberg.de> |
|
70 |
+ */ |
|
71 |
+class ManagedPropertyModel extends Model |
|
72 |
+{ |
|
73 |
+ |
|
74 |
+ /** |
|
75 |
+ * Table name |
|
76 |
+ * @var string |
|
77 |
+ */ |
|
78 |
+ protected static $strTable = 'tl_vr_re_managedProperties'; |
|
79 |
+ |
|
80 |
+ /** |
|
81 |
+ * Find a published assets from one or more categories |
|
82 |
+ * |
|
83 |
+ * @param mixed $varId The numeric id or alias name |
|
84 |
+ * @param array $arrOptions An optional options array |
|
85 |
+ * |
|
86 |
+ * @return ManagedPropertyModel|null A model or null if there is no asset |
|
87 |
+ */ |
|
88 |
+ public static function findPublishedByIdOrAlias($varId, array $arrOptions = array()) |
|
89 |
+ { |
|
90 |
+ $t = static::$strTable; |
|
91 |
+ $arrColumns = !preg_match('/^[1-9]\d*$/', $varId) ? array("BINARY $t.alias=?") : array("$t.id=?"); |
|
92 |
+ |
|
93 |
+ if (!static::isPreviewMode($arrOptions)) |
|
94 |
+ { |
|
95 |
+ $time = Date::floorToMinute(); |
|
96 |
+ $arrColumns[] = "$t.published='1' AND ($t.start='' OR $t.start<='$time') AND ($t.stop='' OR $t.stop>'$time')"; |
|
97 |
+ } |
|
98 |
+ |
|
99 |
+ return static::findOneBy($arrColumns, $varId, $arrOptions); |
|
100 |
+ } |
|
101 |
+ |
|
102 |
+ /** |
|
103 |
+ * Find a published assets from one or more categories |
|
104 |
+ * |
|
105 |
+ * @param array $arrPids An array of parent IDs |
|
106 |
+ * @param integer $intLimit An optional limit |
|
107 |
+ * @param integer $intOffset An optional offset |
|
108 |
+ * @param array $arrOptions An optional options array |
|
109 |
+ * |
|
110 |
+ * @return Collection|ManagedPropertyModel[]|ManagedPropertyModel|null A collection of models or null if there are no assets |
|
111 |
+ */ |
|
112 |
+ public static function findAllPublished($intLimit = 0, $intOffset = 0, array $arrOptions = array()) |
|
113 |
+ { |
|
114 |
+ $t = static::$strTable; |
|
115 |
+ $arrColumns = []; |
|
116 |
+ $arrValues = []; |
|
117 |
+ |
|
118 |
+ if (!static::isPreviewMode($arrOptions)) |
|
119 |
+ { |
|
120 |
+ $time = Date::floorToMinute(); |
|
121 |
+ $arrColumns[] = "$t.published='1' AND ($t.start='' OR $t.start<='$time') AND ($t.stop='' OR $t.stop>'$time')"; |
|
122 |
+ } |
|
123 |
+ |
|
124 |
+ if (!isset($arrOptions['order'])) |
|
125 |
+ { |
|
126 |
+ $arrOptions['order'] = "$t.city ASC, $t.livingSpace ASC"; |
|
127 |
+ } |
|
128 |
+ |
|
129 |
+ $arrOptions['limit'] = $intLimit; |
|
130 |
+ $arrOptions['offset'] = $intOffset; |
|
131 |
+ |
|
132 |
+ if (isset($arrOptions['column'])) |
|
133 |
+ { |
|
134 |
+ $arrColumns = array_merge($arrColumns,array_values($arrOptions['column'])); |
|
135 |
+ unset($arrOptions['column']); |
|
136 |
+ } |
|
137 |
+ if (isset($arrOptions['value'])) |
|
138 |
+ { |
|
139 |
+ $arrValues = array_merge($arrValues,array_values($arrOptions['value'])); |
|
140 |
+ unset($arrOptions['value']); |
|
141 |
+ } |
|
142 |
+ |
|
143 |
+ return static::findBy($arrColumns, $arrValues, $arrOptions); |
|
144 |
+ } |
|
145 |
+ |
|
146 |
+ /** |
|
147 |
+ * Find a published assets from one or more categories |
|
148 |
+ * |
|
149 |
+ * @param array $arrPids An array of parent IDs |
|
150 |
+ * @param array $arrOptions An optional options array |
|
151 |
+ * |
|
152 |
+ * @return integer The number of matching rows |
|
153 |
+ */ |
|
154 |
+ public static function countAllPublished(array $arrOptions = array()) |
|
155 |
+ { |
|
156 |
+ $t = static::$strTable; |
|
157 |
+ $arrColumns = []; |
|
158 |
+ $arrValues = []; |
|
159 |
+ |
|
160 |
+ if (!static::isPreviewMode($arrOptions)) |
|
161 |
+ { |
|
162 |
+ $time = Date::floorToMinute(); |
|
163 |
+ $arrColumns[] = "$t.published='1' AND ($t.start='' OR $t.start<='$time') AND ($t.stop='' OR $t.stop>'$time')"; |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ if (isset($arrOptions['column'])) |
|
167 |
+ { |
|
168 |
+ $arrColumns = array_merge($arrColumns,array_values($arrOptions['column'])); |
|
169 |
+ unset($arrOptions['column']); |
|
170 |
+ } |
|
171 |
+ if (isset($arrOptions['value'])) |
|
172 |
+ { |
|
173 |
+ $arrValues = array_merge($arrValues,array_values($arrOptions['value'])); |
|
174 |
+ unset($arrOptions['value']); |
|
175 |
+ } |
|
176 |
+ return static::countBy($arrColumns, $arrValues, $arrOptions); |
|
177 |
+ } |
|
178 |
+} |