f-box file-content tab-size-8" id="diff-36">

backend/migrations/0023_place.py → app/backend/migrations/0023_place.py
Просмотреть файл


+ 22 - 0
app/backend/migrations/0024_points.py

@@ -0,0 +1,22 @@
1
+# Generated by Django 3.2.5 on 2021-07-19 08:11
2
+
3
+from django.db import migrations, models
4
+import django.db.models.deletion
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('backend', '0023_place'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.CreateModel(
15
+            name='Points',
16
+            fields=[
17
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18
+                ('dest', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='dest', to='backend.place')),
19
+                ('src', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='src', to='backend.place')),
20
+            ],
21
+        ),
22
+    ]

+ 28 - 0
app/backend/migrations/0025_auto_20210721_1145.py

@@ -0,0 +1,28 @@
1
+# Generated by Django 3.2.5 on 2021-07-21 04:45
2
+
3
+from django.db import migrations
4
+import django_google_maps.fields
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('backend', '0024_points'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.RemoveField(
15
+            model_name='points',
16
+            name='src',
17
+        ),
18
+        migrations.AddField(
19
+            model_name='points',
20
+            name='address',
21
+            field=django_google_maps.fields.AddressField(max_length=200, null=True),
22
+        ),
23
+        migrations.AddField(
24
+            model_name='points',
25
+            name='geolocation',
26
+            field=django_google_maps.fields.GeoLocationField(max_length=100, null=True),
27
+        ),
28
+    ]

+ 23 - 0
app/backend/migrations/0026_auto_20210721_1218.py

@@ -0,0 +1,23 @@
1
+# Generated by Django 3.2.5 on 2021-07-21 05:18
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('backend', '0025_auto_20210721_1145'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='points',
15
+            name='distance',
16
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True),
17
+        ),
18
+        migrations.AddField(
19
+            model_name='points',
20
+            name='duration',
21
+            field=models.CharField(blank=True, max_length=200, null=True),
22
+        ),
23
+    ]

+ 23 - 0
app/backend/migrations/0027_auto_20210721_1251.py

@@ -0,0 +1,23 @@
1
+# Generated by Django 3.2.5 on 2021-07-21 05:51
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('backend', '0026_auto_20210721_1218'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='points',
15
+            name='directions',
16
+            field=models.JSONField(blank=True, null=True),
17
+        ),
18
+        migrations.AlterField(
19
+            model_name='points',
20
+            name='distance',
21
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True, verbose_name='Distance (km)'),
22
+        ),
23
+    ]

+ 18 - 0
app/backend/migrations/0028_place_title.py

@@ -0,0 +1,18 @@
1
+# Generated by Django 3.2.5 on 2021-07-21 10:11
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('backend', '0027_auto_20210721_1251'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='place',
15
+            name='title',
16
+            field=models.CharField(blank=True, max_length=200, null=True),
17
+        ),
18
+    ]

+ 20 - 0
app/backend/migrations/0029_importfile.py

@@ -0,0 +1,20 @@
1
+# Generated by Django 3.2.5 on 2021-07-22 08:04
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('backend', '0028_place_title'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.CreateModel(
14
+            name='ImportFile',
15
+            fields=[
16
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17
+                ('hospital_file', models.FileField(blank=True, upload_to='uploads/%Y/%m/%d/', verbose_name='Hospital (csv)')),
18
+            ],
19
+        ),
20
+    ]

backend/migrations/__init__.py → app/backend/migrations/__init__.py


backend/migrations/__pycache__/0001_initial.cpython-39.pyc → app/backend/migrations/__pycache__/0001_initial.cpython-39.pyc


backend/migrations/__pycache__/0002_hospital_geolocation.cpython-39.pyc → app/backend/migrations/__pycache__/0002_hospital_geolocation.cpython-39.pyc


backend/migrations/__pycache__/0003_alter_hospital_address.cpython-39.pyc → app/backend/migrations/__pycache__/0003_alter_hospital_address.cpython-39.pyc


backend/migrations/__pycache__/0004_alter_hospital_location.cpython-39.pyc → app/backend/migrations/__pycache__/0004_alter_hospital_location.cpython-39.pyc


backend/migrations/__pycache__/0005_hospital_address_text.cpython-39.pyc → app/backend/migrations/__pycache__/0005_hospital_address_text.cpython-39.pyc


backend/migrations/__pycache__/0006_bed_patient.cpython-39.pyc → app/backend/migrations/__pycache__/0006_bed_patient.cpython-39.pyc


backend/migrations/__pycache__/0007_auto_20210718_0246.cpython-39.pyc → app/backend/migrations/__pycache__/0007_auto_20210718_0246.cpython-39.pyc


backend/migrations/__pycache__/0007_auto_20210718_0249.cpython-39.pyc → app/backend/migrations/__pycache__/0007_auto_20210718_0249.cpython-39.pyc


backend/migrations/__pycache__/0008_alter_patient_prefix.cpython-39.pyc → app/backend/migrations/__pycache__/0008_alter_patient_prefix.cpython-39.pyc


backend/migrations/__pycache__/0008_auto_20210718_0659.cpython-39.pyc → app/backend/migrations/__pycache__/0008_auto_20210718_0659.cpython-39.pyc


backend/migrations/__pycache__/0009_auto_20210718_0702.cpython-39.pyc → app/backend/migrations/__pycache__/0009_auto_20210718_0702.cpython-39.pyc


backend/migrations/__pycache__/0010_auto_20210718_0711.cpython-39.pyc → app/backend/migrations/__pycache__/0010_auto_20210718_0711.cpython-39.pyc


backend/migrations/__pycache__/0010_auto_20210718_0713.cpython-39.pyc → app/backend/migrations/__pycache__/0010_auto_20210718_0713.cpython-39.pyc


backend/migrations/__pycache__/0011_auto_20210718_0722.cpython-39.pyc → app/backend/migrations/__pycache__/0011_auto_20210718_0722.cpython-39.pyc


backend/migrations/__pycache__/0012_patient_comment.cpython-39.pyc → app/backend/migrations/__pycache__/0012_patient_comment.cpython-39.pyc


backend/migrations/__pycache__/0013_patientlog.cpython-39.pyc → app/backend/migrations/__pycache__/0013_patientlog.cpython-39.pyc


backend/migrations/__pycache__/0014_alter_patientlog_bed.cpython-39.pyc → app/backend/migrations/__pycache__/0014_alter_patientlog_bed.cpython-39.pyc


backend/migrations/__pycache__/0015_alter_patientlog_bed.cpython-39.pyc → app/backend/migrations/__pycache__/0015_alter_patientlog_bed.cpython-39.pyc


backend/migrations/__pycache__/0016_auto_20210718_1031.cpython-39.pyc → app/backend/migrations/__pycache__/0016_auto_20210718_1031.cpython-39.pyc


backend/migrations/__pycache__/0017_ambulance_driver.cpython-39.pyc → app/backend/migrations/__pycache__/0017_ambulance_driver.cpython-39.pyc


backend/migrations/__pycache__/0018_ambulance_color.cpython-39.pyc → app/backend/migrations/__pycache__/0018_ambulance_color.cpython-39.pyc


backend/migrations/__pycache__/0019_ambulanceticket.cpython-39.pyc → app/backend/migrations/__pycache__/0019_ambulanceticket.cpython-39.pyc


backend/migrations/__pycache__/0020_driver_status.cpython-39.pyc → app/backend/migrations/__pycache__/0020_driver_status.cpython-39.pyc


backend/migrations/__pycache__/0021_auto_20210719_0014.cpython-39.pyc → app/backend/migrations/__pycache__/0021_auto_20210719_0014.cpython-39.pyc


backend/migrations/__pycache__/0022_auto_20210719_0024.cpython-39.pyc → app/backend/migrations/__pycache__/0022_auto_20210719_0024.cpython-39.pyc


backend/migrations/__pycache__/0023_place.cpython-39.pyc → app/backend/migrations/__pycache__/0023_place.cpython-39.pyc


BIN
app/backend/migrations/__pycache__/0024_points.cpython-39.pyc


BIN
app/backend/migrations/__pycache__/0025_auto_20210721_1145.cpython-39.pyc


BIN
app/backend/migrations/__pycache__/0026_auto_20210721_1218.cpython-39.pyc


BIN
app/backend/migrations/__pycache__/0027_auto_20210721_1251.cpython-39.pyc


BIN
app/backend/migrations/__pycache__/0028_place_title.cpython-39.pyc


BIN
app/backend/migrations/__pycache__/0029_importfile.cpython-39.pyc


backend/migrations/__pycache__/__init__.cpython-39.pyc → app/backend/migrations/__pycache__/__init__.cpython-39.pyc


+ 96 - 0
backend/models.py

@@ -8,6 +8,13 @@ from smart_selects.db_fields import (
8 8
     ChainedManyToManyField,
9 9
     GroupedForeignKey,
10 10
 )
11
+import googlemaps
12
+from django.contrib.gis.geos import fromstr
13
+
14
+from django.conf import settings
15
+import csv
16
+
17
+gmaps = googlemaps.Client(key=settings.GOOGLE_MAPS_API_KEY)
11 18
 # Create your models here.
12 19
 GENDER_CHOICES = (
13 20
     ('นางสาว','นางสาว'),
@@ -122,9 +129,66 @@ class Patient(models.Model):
122 129
     comment  = models.TextField(blank=True, null=True)
123 130
     #test
124 131
     def __str__(self):
132
+        #self.nearby()
125 133
         return f"{self.first_name} {self.last_name}"
126 134
 
135
+
136
+    def nearby(self):
137
+        r = gmaps.places_nearby(location=(self.geolocation.lat, self.geolocation.lon), type="hospital", radius=10000)
138
+        bd = ""
139
+        for r0 in r['results']:
140
+            openh = "-"
141
+            if 'opening_hours' in r0:
142
+                openh = r0['opening_hours']['open_now']
143
+            else:
144
+                openh = "-"
145
+
146
+            bd += f"<tr><td>{r0['name']}</td><td>{openh}</td><td>{r0['vicinity']}</td></tr>"
147
+
148
+        rt = f'''
149
+<br>
150
+        <table><thead><tr><th>Name</th><th>Opening Hours</th><th>Vicinity</th></tr></thead>
151
+        <tbody>
152
+            {bd}
153
+        </tbody>
154
+        </table>
155
+        '''
156
+        return rt
157
+
158
+
159
+
160
+class ImportFile(models.Model):
161
+    hospital_file  = models.FileField(upload_to="uploads/%Y/%m/%d/", blank=True, verbose_name="Hospital (csv)")
162
+
163
+    def save(self, *args, **kwargs):
164
+        super(ImportFile, self).save(*args, **kwargs)
165
+
166
+        with self.hospital_file.open('r') as csv_file:
167
+            csv_reader = csv.reader(csv_file, delimiter=',')
168
+            Hospital.objects.all().delete()
169
+            line_count = 0
170
+
171
+            for r in csv_reader:
172
+                if line_count > 0:
173
+                    print(r)
174
+                    print(f"{r[7]},{r[6]}")
175
+                    try:
176
+                        gp = map_fields.GeoPt(lat=float(r[6]), lon=float(r[7]))
177
+
178
+                        location = fromstr(f'POINT({r[7]} {r[6]})', srid=4326)
179
+                        print(location)
180
+                        h = Hospital(title=r[3], address_text=r[5], geolocation=gp, address=r[3])
181
+                        h.save()
182
+                    except Exception as e:
183
+                        print(e)
184
+
185
+                line_count += 1
186
+
187
+
188
+
127 189
 class Place(models.Model):
190
+    #title  = models.Char
191
+    title = models.CharField(max_length=200, blank=True, null=True)
128 192
     address = map_fields.AddressField(max_length=200)
129 193
     geolocation = map_fields.GeoLocationField(max_length=100)
130 194
 
@@ -133,6 +197,36 @@ class Place(models.Model):
133 197
 
134 198
     more_info  = models.JSONField(null=True, blank=True)
135 199
 
200
+    def __str__(self):
201
+        return f"{self.address} ({self.geolocation})"
202
+class Points(models.Model):
203
+    #src  = models.ForeignKey(Place, on_delete=models.SET_NULL, null=True, blank=False, related_name='src')
204
+    dest  = models.ForeignKey(Place, on_delete=models.SET_NULL, null=True, blank=False, related_name='dest')
205
+    address = map_fields.AddressField(max_length=200, null=True)
206
+    geolocation = map_fields.GeoLocationField(max_length=100, null=True)
207
+
208
+    distance = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=7, verbose_name="Distance (km)")
209
+    duration = models.CharField(max_length=200, null=True, blank=True)
210
+
211
+    directions  = models.JSONField(null=True, blank=True)
212
+
213
+    def save(self, *args, **kwargs):
214
+        geocode_result = gmaps.geocode('1600 Amphitheatre Parkway, Mountain View, CA')
215
+        print(geocode_result)
216
+        print(self.geolocation)
217
+        origin = [(self.geolocation.lat, self.geolocation.lon)]
218
+        dest = [(self.dest.geolocation.lat, self.dest.geolocation.lon)]
219
+        dst = gmaps.distance_matrix(origin, dest)
220
+        dirs = gmaps.directions(origin[0], dest[0])
221
+        self.directions = dirs
222
+        print(dirs)
223
+        self.distance = dst['rows'][0]['elements'][0]['distance']['value'] / 1000
224
+        self.duration = dst['rows'][0]['elements'][0]['duration']['text']
225
+        print(dst)
226
+        super(Points, self).save(*args, **kwargs)
227
+
228
+
229
+
136 230
 class Hospital(models.Model):
137 231
     title = models.CharField(max_length=200)
138 232
     location = models.PointField(blank=True, null=True)
@@ -190,3 +284,5 @@ class PatientLog(models.Model):
190 284
     updated_at = models.DateTimeField(auto_now=True)
191 285
 
192 286
 
287
+
288
+

+ 7 - 0
app/backend/templates/backend/import_file.html

@@ -0,0 +1,7 @@
1
+{% extends "base.html" %}
2
+
3
+{% block title %}My amazing blog{% endblock %}
4
+
5
+{% block content %}
6
+Import File
7
+{% endblock %}

+ 8 - 0
app/backend/templates/backend/index.html

@@ -0,0 +1,8 @@
1
+{% extends "base.html" %}
2
+
3
+{% block title %}My amazing blog{% endblock %}
4
+
5
+{% block content %}
6
+Hello world
7
+<a href="{% url "import_file" %}">Import</a>
8
+{% endblock %}

backend/tests.py → app/backend/tests.py


+ 1 - 0
backend/urls.py

@@ -4,4 +4,5 @@ from . import views
4 4
 
5 5
 urlpatterns = [
6 6
     path('', views.index, name='index'),
7
+    path('import_file', views.import_file, name='import_file'),
7 8
 ]

+ 11 - 0
app/backend/views.py

@@ -0,0 +1,11 @@
1
+from django.shortcuts import render
2
+
3
+# Create your views here.
4
+from django.http import HttpResponse
5
+
6
+
7
+def index(request):
8
+    return render(request, 'backend/index.html')
9
+
10
+def import_file(request):
11
+    return render(request, 'backend/import_file.html')

manage.py → app/manage.py


uploads/2021/07/18/67224.jpg → app/media/uploads/2021/07/18/67224.jpg


Разница между файлами не показана из-за своего большого размера
+ 10715 - 0
app/media/uploads/2021/07/22/citizeninfo_health_20200314.csv


Разница между файлами не показана из-за своего большого размера
+ 10715 - 0
app/media/uploads/2021/07/22/citizeninfo_health_20200314_W9jk8Vu.csv


+ 1 - 0
requirements.txt

@@ -5,3 +5,4 @@ django-smart-selects
5 5
 django-colorfield
6 6
 googlemaps
7 7
 django-json-widget
8
+django-import-export

backend/__init__.py → app/shaqfindbed/__init__.py


shaqfindbed/__pycache__/__init__.cpython-39.pyc → app/shaqfindbed/__pycache__/__init__.cpython-39.pyc


BIN
app/shaqfindbed/__pycache__/settings.cpython-39.pyc


BIN
shaqfindbed/__pycache__/urls.cpython-39.pyc


shaqfindbed/__pycache__/wsgi.cpython-39.pyc → app/shaqfindbed/__pycache__/wsgi.cpython-39.pyc


shaqfindbed/asgi.py → app/shaqfindbed/asgi.py


+ 3 - 2
shaqfindbed/settings.py

@@ -33,12 +33,13 @@ ALLOWED_HOSTS = []
33 33
 # Application definition
34 34
 
35 35
 INSTALLED_APPS = [
36
+    'django.contrib.staticfiles',
36 37
     'django.contrib.admin',
37 38
     'django.contrib.auth',
38 39
     'django.contrib.contenttypes',
39 40
     'django.contrib.sessions',
40 41
     'django.contrib.messages',
41
-    'django.contrib.staticfiles',
42
+    'import_export',
42 43
     'django_google_maps',
43 44
     'django.contrib.gis',
44 45
     'smart_selects',
@@ -62,7 +63,7 @@ ROOT_URLCONF = 'shaqfindbed.urls'
62 63
 TEMPLATES = [
63 64
     {
64 65
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
65
-        'DIRS': [],
66
+        'DIRS': [os.path.join(BASE_DIR, 'templates')],
66 67
         'APP_DIRS': True,
67 68
         'OPTIONS': {
68 69
             'context_processors': [

+ 1 - 1
shaqfindbed/urls.py

@@ -23,7 +23,7 @@ urlpatterns = [
23 23
     path('backend/', include('backend.urls')),
24 24
     path('admin/', admin.site.urls),
25 25
     url(r'^chaining/', include('smart_selects.urls')),
26
-]
26
+] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
27 27
 
28 28
 if settings.DEBUG:
29 29
     urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

shaqfindbed/wsgi.py → app/shaqfindbed/wsgi.py


BIN
app/static/.DS_Store


BIN
app/static/admin/.DS_Store


staticfile/admin/css/autocomplete.css → app/static/admin/css/autocomplete.css


+ 0 - 0
staticfile/admin/css/base.css


Некоторые файлы не были показаны из-за большого количества измененных файлов

tum/whitesports - Gogs: Simplico Git Service

Brak opisu

local-fields.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. <?php
  2. // Register notices stores.
  3. acf_register_store( 'local-fields' );
  4. acf_register_store( 'local-groups' );
  5. acf_register_store( 'local-empty' );
  6. // Register filter.
  7. acf_enable_filter( 'local' );
  8. /**
  9. * acf_enable_local
  10. *
  11. * Enables the local filter.
  12. *
  13. * @date 22/1/19
  14. * @since 5.7.10
  15. *
  16. * @param void
  17. * @return void
  18. */
  19. function acf_enable_local() {
  20. acf_enable_filter( 'local' );
  21. }
  22. /**
  23. * acf_disable_local
  24. *
  25. * Disables the local filter.
  26. *
  27. * @date 22/1/19
  28. * @since 5.7.10
  29. *
  30. * @param void
  31. * @return void
  32. */
  33. function acf_disable_local() {
  34. acf_disable_filter( 'local' );
  35. }
  36. /**
  37. * acf_is_local_enabled
  38. *
  39. * Returns true if local fields are enabled.
  40. *
  41. * @date 23/1/19
  42. * @since 5.7.10
  43. *
  44. * @param void
  45. * @return bool
  46. */
  47. function acf_is_local_enabled() {
  48. return ( acf_is_filter_enabled( 'local' ) && acf_get_setting( 'local' ) );
  49. }
  50. /**
  51. * acf_get_local_store
  52. *
  53. * Returns either local store or a dummy store for the given name.
  54. *
  55. * @date 23/1/19
  56. * @since 5.7.10
  57. *
  58. * @param string $name The store name (fields|groups).
  59. * @return ACF_Data
  60. */
  61. function acf_get_local_store( $name = '' ) {
  62. // Check if enabled.
  63. if ( acf_is_local_enabled() ) {
  64. return acf_get_store( "local-$name" );
  65. // Return dummy store if not enabled.
  66. } else {
  67. return acf_get_store( 'local-empty' );
  68. }
  69. }
  70. /**
  71. * acf_reset_local
  72. *
  73. * Resets the local data.
  74. *
  75. * @date 22/1/19
  76. * @since 5.7.10
  77. *
  78. * @param void
  79. * @return void
  80. */
  81. function acf_reset_local() {
  82. acf_get_local_store( 'fields' )->reset();
  83. acf_get_local_store( 'groups' )->reset();
  84. }
  85. /**
  86. * acf_get_local_field_groups
  87. *
  88. * Returns all local field groups.
  89. *
  90. * @date 22/1/19
  91. * @since 5.7.10
  92. *
  93. * @param void
  94. * @return array
  95. */
  96. function acf_get_local_field_groups() {
  97. return acf_get_local_store( 'groups' )->get();
  98. }
  99. /**
  100. * acf_have_local_field_groups
  101. *
  102. * description
  103. *
  104. * @date 22/1/19
  105. * @since 5.7.10
  106. *
  107. * @param type $var Description. Default.
  108. * @return type Description.
  109. */
  110. function acf_have_local_field_groups() {
  111. return acf_get_local_store( 'groups' )->count() ? true : false;
  112. }
  113. /**
  114. * acf_count_local_field_groups
  115. *
  116. * description
  117. *
  118. * @date 22/1/19
  119. * @since 5.7.10
  120. *
  121. * @param type $var Description. Default.
  122. * @return type Description.
  123. */
  124. function acf_count_local_field_groups() {
  125. return acf_get_local_store( 'groups' )->count();
  126. }
  127. /**
  128. * acf_add_local_field_group
  129. *
  130. * Adds a local field group.
  131. *
  132. * @date 22/1/19
  133. * @since 5.7.10
  134. *
  135. * @param array $field_group The field group array.
  136. * @return bool
  137. */
  138. function acf_add_local_field_group( $field_group ) {
  139. // Apply default properties needed for import.
  140. $field_group = wp_parse_args(
  141. $field_group,
  142. array(
  143. 'key' => '',
  144. 'title' => '',
  145. 'fields' => array(),
  146. 'local' => 'php',
  147. )
  148. );
  149. // Generate key if only name is provided.
  150. if ( ! $field_group['key'] ) {
  151. $field_group['key'] = 'group_' . acf_slugify( $field_group['title'], '_' );
  152. }
  153. // Bail early if field group already exists.
  154. if ( acf_is_local_field_group( $field_group['key'] ) ) {
  155. return false;
  156. }
  157. // Prepare field group for import (adds menu_order and parent properties to fields).
  158. $field_group = acf_prepare_field_group_for_import( $field_group );
  159. // Extract fields from group.
  160. $fields = acf_extract_var( $field_group, 'fields' );
  161. // Add to store
  162. acf_get_local_store( 'groups' )->set( $field_group['key'], $field_group );
  163. // Add fields
  164. if ( $fields ) {
  165. acf_add_local_fields( $fields );
  166. }
  167. // Return true on success.
  168. return true;
  169. }
  170. /**
  171. * register_field_group
  172. *
  173. * See acf_add_local_field_group().
  174. *
  175. * @date 22/1/19
  176. * @since 5.7.10
  177. *
  178. * @param array $field_group The field group array.
  179. * @return void
  180. */
  181. function register_field_group( $field_group ) {
  182. acf_add_local_field_group( $field_group );
  183. }
  184. /**
  185. * acf_remove_local_field_group
  186. *
  187. * Removes a field group for the given key.
  188. *
  189. * @date 22/1/19
  190. * @since 5.7.10
  191. *
  192. * @param string $key The field group key.
  193. * @return bool
  194. */
  195. function acf_remove_local_field_group( $key = '' ) {
  196. return acf_get_local_store( 'groups' )->remove( $key );
  197. }
  198. /**
  199. * acf_is_local_field_group
  200. *
  201. * Returns true if a field group exists for the given key.
  202. *
  203. * @date 22/1/19
  204. * @since 5.7.10
  205. *
  206. * @param string $key The field group key.
  207. * @return bool
  208. */
  209. function acf_is_local_field_group( $key = '' ) {
  210. return acf_get_local_store( 'groups' )->has( $key );
  211. }
  212. /**
  213. * acf_is_local_field_group_key
  214. *
  215. * Returns true if a field group exists for the given key.
  216. *
  217. * @date 22/1/19
  218. * @since 5.7.10
  219. *
  220. * @param string $key The field group group key.
  221. * @return bool
  222. */
  223. function acf_is_local_field_group_key( $key = '' ) {
  224. return acf_get_local_store( 'groups' )->is( $key );
  225. }
  226. /**
  227. * acf_get_local_field_group
  228. *
  229. * Returns a field group for the given key.
  230. *
  231. * @date 22/1/19
  232. * @since 5.7.10
  233. *
  234. * @param string $key The field group key.
  235. * @return (array|null)
  236. */
  237. function acf_get_local_field_group( $key = '' ) {
  238. return acf_get_local_store( 'groups' )->get( $key );
  239. }
  240. /**
  241. * acf_add_local_fields
  242. *
  243. * Adds an array of local fields.
  244. *
  245. * @date 22/1/19
  246. * @since 5.7.10
  247. *
  248. * @param array $fields An array of un prepared fields.
  249. * @return array
  250. */
  251. function acf_add_local_fields( $fields = array() ) {
  252. // Prepare for import (allows parent fields to offer up children).
  253. $fields = acf_prepare_fields_for_import( $fields );
  254. // Add each field.
  255. foreach ( $fields as $field ) {
  256. acf_add_local_field( $field, true );
  257. }
  258. }
  259. /**
  260. * acf_get_local_fields
  261. *
  262. * Returns all local fields for the given parent.
  263. *
  264. * @date 22/1/19
  265. * @since 5.7.10
  266. *
  267. * @param string $parent The parent key.
  268. * @return array
  269. */
  270. function acf_get_local_fields( $parent = '' ) {
  271. // Return children
  272. if ( $parent ) {
  273. return acf_get_local_store( 'fields' )->query(
  274. array(
  275. 'parent' => $parent,
  276. )
  277. );
  278. // Return all.
  279. } else {
  280. return acf_get_local_store( 'fields' )->get();
  281. }
  282. }
  283. /**
  284. * acf_have_local_fields
  285. *
  286. * Returns true if local fields exist.
  287. *
  288. * @date 22/1/19
  289. * @since 5.7.10
  290. *
  291. * @param string $parent The parent key.
  292. * @return bool
  293. */
  294. function acf_have_local_fields( $parent = '' ) {
  295. return acf_get_local_fields( $parent ) ? true : false;
  296. }
  297. /**
  298. * acf_count_local_fields
  299. *
  300. * Returns the number of local fields for the given parent.
  301. *
  302. * @date 22/1/19
  303. * @since 5.7.10
  304. *
  305. * @param string $parent The parent key.
  306. * @return int
  307. */
  308. function acf_count_local_fields( $parent = '' ) {
  309. return count( acf_get_local_fields( $parent ) );
  310. }
  311. /**
  312. * acf_add_local_field
  313. *
  314. * Adds a local field.
  315. *
  316. * @date 22/1/19
  317. * @since 5.7.10
  318. *
  319. * @param array $field The field array.
  320. * @param bool $prepared Whether or not the field has already been prepared for import.
  321. * @return void
  322. */
  323. function acf_add_local_field( $field, $prepared = false ) {
  324. // Apply default properties needed for import.
  325. $field = wp_parse_args(
  326. $field,
  327. array(
  328. 'key' => '',
  329. 'name' => '',
  330. 'type' => '',
  331. 'parent' => '',
  332. )
  333. );
  334. // Generate key if only name is provided.
  335. if ( ! $field['key'] ) {
  336. $field['key'] = 'field_' . $field['name'];
  337. }
  338. // If called directly, allow sub fields to be correctly prepared.
  339. if ( ! $prepared ) {
  340. return acf_add_local_fields( array( $field ) );
  341. }
  342. // Extract attributes.
  343. $key = $field['key'];
  344. $name = $field['name'];
  345. // Allow sub field to be added multipel times to different parents.
  346. $store = acf_get_local_store( 'fields' );
  347. if ( $store->is( $key ) ) {
  348. $old_key = _acf_generate_local_key( $store->get( $key ) );
  349. $new_key = _acf_generate_local_key( $field );
  350. if ( $old_key !== $new_key ) {
  351. $key = $new_key;
  352. }
  353. }
  354. // Add field.
  355. $store->set( $key, $field )->alias( $key, $name );
  356. }
  357. /**
  358. * _acf_generate_local_key
  359. *
  360. * Generates a unique key based on the field's parent.
  361. *
  362. * @date 22/1/19
  363. * @since 5.7.10
  364. *
  365. * @param string $key The field key.
  366. * @return bool
  367. */
  368. function _acf_generate_local_key( $field ) {
  369. return "{$field['key']}:{$field['parent']}";
  370. }
  371. /**
  372. * acf_remove_local_field
  373. *
  374. * Removes a field for the given key.
  375. *
  376. * @date 22/1/19
  377. * @since 5.7.10
  378. *
  379. * @param string $key The field key.
  380. * @return bool
  381. */
  382. function acf_remove_local_field( $key = '' ) {
  383. return acf_get_local_store( 'fields' )->remove( $key );
  384. }
  385. /**
  386. * acf_is_local_field
  387. *
  388. * Returns true if a field exists for the given key or name.
  389. *
  390. * @date 22/1/19
  391. * @since 5.7.10
  392. *
  393. * @param string $key The field group key.
  394. * @return bool
  395. */
  396. function acf_is_local_field( $key = '' ) {
  397. return acf_get_local_store( 'fields' )->has( $key );
  398. }
  399. /**
  400. * acf_is_local_field_key
  401. *
  402. * Returns true if a field exists for the given key.
  403. *
  404. * @date 22/1/19
  405. * @since 5.7.10
  406. *
  407. * @param string $key The field group key.
  408. * @return bool
  409. */
  410. function acf_is_local_field_key( $key = '' ) {
  411. return acf_get_local_store( 'fields' )->is( $key );
  412. }
  413. /**
  414. * acf_get_local_field
  415. *
  416. * Returns a field for the given key.
  417. *
  418. * @date 22/1/19
  419. * @since 5.7.10
  420. *
  421. * @param string $key The field group key.
  422. * @return (array|null)
  423. */
  424. function acf_get_local_field( $key = '' ) {
  425. return acf_get_local_store( 'fields' )->get( $key );
  426. }
  427. /**
  428. * _acf_apply_get_local_field_groups
  429. *
  430. * Appends local field groups to the provided array.
  431. *
  432. * @date 23/1/19
  433. * @since 5.7.10
  434. *
  435. * @param array $field_groups An array of field groups.
  436. * @return array
  437. */
  438. function _acf_apply_get_local_field_groups( $groups = array() ) {
  439. // Get local groups
  440. $local = acf_get_local_field_groups();
  441. if ( $local ) {
  442. // Generate map of "index" => "key" data.
  443. $map = wp_list_pluck( $groups, 'key' );
  444. // Loop over groups and update/append local.
  445. foreach ( $local as $group ) {
  446. // Get group allowing cache and filters to run.
  447. // $group = acf_get_field_group( $group['key'] );
  448. // Update.
  449. $i = array_search( $group['key'], $map );
  450. if ( $i !== false ) {
  451. unset( $group['ID'] );
  452. $groups[ $i ] = array_merge( $groups[ $i ], $group );
  453. // Append
  454. } else {
  455. $groups[] = acf_get_field_group( $group['key'] );
  456. }
  457. }
  458. // Sort list via menu_order and title.
  459. $groups = wp_list_sort(
  460. $groups,
  461. array(
  462. 'menu_order' => 'ASC',
  463. 'title' => 'ASC',
  464. )
  465. );
  466. }
  467. // Return groups.
  468. return $groups;
  469. }
  470. // Hook into filter.
  471. add_filter( 'acf/load_field_groups', '_acf_apply_get_local_field_groups', 20, 1 );
  472. /**
  473. * _acf_apply_is_local_field_key
  474. *
  475. * Returns true if is a local key.
  476. *
  477. * @date 23/1/19
  478. * @since 5.7.10
  479. *
  480. * @param bool $bool The result.
  481. * @param string $id The identifier.
  482. * @return bool
  483. */
  484. function _acf_apply_is_local_field_key( $bool, $id ) {
  485. return acf_is_local_field_key( $id );
  486. }
  487. // Hook into filter.
  488. add_filter( 'acf/is_field_key', '_acf_apply_is_local_field_key', 20, 2 );
  489. /**
  490. * _acf_apply_is_local_field_group_key
  491. *
  492. * Returns true if is a local key.
  493. *
  494. * @date 23/1/19
  495. * @since 5.7.10
  496. *
  497. * @param bool $bool The result.
  498. * @param string $id The identifier.
  499. * @return bool
  500. */
  501. function _acf_apply_is_local_field_group_key( $bool, $id ) {
  502. return acf_is_local_field_group_key( $id );
  503. }
  504. // Hook into filter.
  505. add_filter( 'acf/is_field_group_key', '_acf_apply_is_local_field_group_key', 20, 2 );
  506. /**
  507. * _acf_do_prepare_local_fields
  508. *
  509. * Local fields that are added too early will not be correctly prepared by the field type class.
  510. *
  511. * @date 23/1/19
  512. * @since 5.7.10
  513. *
  514. * @param void
  515. * @return void
  516. */
  517. function _acf_do_prepare_local_fields() {
  518. // Get fields.
  519. $fields = acf_get_local_fields();
  520. // If fields have been registered early, re-add to correctly prepare them.
  521. if ( $fields ) {
  522. acf_add_local_fields( $fields );
  523. }
  524. }
  525. // Hook into action.
  526. add_action( 'acf/include_fields', '_acf_do_prepare_local_fields', 0, 1 );