Backend: Refactor entity package
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
7d840d4a46
commit
260cca91fe
55 changed files with 329 additions and 323 deletions
4
go.mod
4
go.mod
|
@ -1,7 +1,6 @@
|
|||
module github.com/photoprism/photoprism
|
||||
|
||||
require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3 // indirect
|
||||
github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
|
||||
github.com/coreos/etcd v3.3.10+incompatible // indirect
|
||||
|
@ -55,11 +54,9 @@ require (
|
|||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/sevlyar/go-daemon v0.1.5
|
||||
github.com/shopspring/decimal v0.0.0-20191130220710-360f2bc03045 // indirect
|
||||
github.com/simplereach/timeutils v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.5.0
|
||||
github.com/soheilhy/cmux v0.1.4 // indirect
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 // indirect
|
||||
github.com/stretchr/objx v0.2.0 // indirect
|
||||
github.com/stretchr/testify v1.5.1
|
||||
github.com/studio-b12/gowebdav v0.0.0-20200303150724-9380631c29a1
|
||||
github.com/tensorflow/tensorflow v1.15.2
|
||||
|
@ -80,7 +77,6 @@ require (
|
|||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||
golang.org/x/tools v0.0.0-20200401192744-099440627f01 // indirect
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
|
||||
gopkg.in/stretchr/testify.v1 v1.2.2 // indirect
|
||||
gopkg.in/ugjka/go-tz.v2 v2.0.8
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
|
|
40
go.sum
40
go.sum
|
@ -5,8 +5,6 @@ cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
|
|||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||
|
@ -17,8 +15,6 @@ github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 h1:Fv9bK1Q+ly/ROk4aJ
|
|||
github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/araddon/dateparse v0.0.0-20181123171228-21df004e09ca h1:7tLEgJZb8/+TI8fLso4lINkuSOI4DqQYwhFB+nRH7RQ=
|
||||
github.com/araddon/dateparse v0.0.0-20181123171228-21df004e09ca/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
|
||||
github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195 h1:c4mLfegoDw6OhSJXTd2jUEQgZUQuJWtocudb97Qn9EM=
|
||||
github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
|
||||
github.com/beorn7/perks v0.0.0-20160229213445-3ac7bf7a47d1/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
|
@ -63,32 +59,22 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
|
|||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/djherbis/times v1.1.0 h1:NFhBDODme0XNX+/5ETW9qL6v3Ty57psiXIQBrzzg44E=
|
||||
github.com/djherbis/times v1.1.0/go.mod h1:CGMZlo255K5r4Yw0b9RRfFQpM2y7uOmxg4jm9HsaVf8=
|
||||
github.com/djherbis/times v1.2.0 h1:xANXjsC/iBqbO00vkWlYwPWgBgEVU6m6AFYg0Pic+Mc=
|
||||
github.com/djherbis/times v1.2.0/go.mod h1:CGMZlo255K5r4Yw0b9RRfFQpM2y7uOmxg4jm9HsaVf8=
|
||||
github.com/dsoprea/go-exif/v2 v2.0.0-20200113231207-0bbb7a3584f7 h1:+koSu4BOaLu+dy50WEj+ltzEjMzK5evzPawKxgIQerw=
|
||||
github.com/dsoprea/go-exif/v2 v2.0.0-20200113231207-0bbb7a3584f7/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
|
||||
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4 h1:bVaiYo8amn7Lu93sz6mTlYB3EtLG9aRcMnM1Eps8fmM=
|
||||
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
|
||||
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200113231507-4c1dccae8069 h1:z1wUugJVR5E3jZrXiqzzK4Bgws2YN3R7G0N49AqiykM=
|
||||
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200113231507-4c1dccae8069/go.mod h1:J/Nq2z38/2hLpCvcXMVPYI28WN7+sgYpzZ3+jtcj+6U=
|
||||
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200401235850-9261959559e1 h1:EQeJZeebsYbccEzUMOpYNXB9AkMZxOmb7x2LgdHhZ3c=
|
||||
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200401235850-9261959559e1/go.mod h1:5vwlfhyZI7u8AuvTl0G70sdqVdH41f7dscvBQ6mEbHs=
|
||||
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200419165912-75b7a4f392e6 h1:6oyE0L+MX1iUjldwrLdAaU95g36UrKpbmlyslhyoJj4=
|
||||
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200419165912-75b7a4f392e6/go.mod h1:5vwlfhyZI7u8AuvTl0G70sdqVdH41f7dscvBQ6mEbHs=
|
||||
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 h1:VGFnZAcLwPpt1sHlAxml+pGLZz9A2s+K/s1YNhPC91Y=
|
||||
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
|
||||
github.com/dsoprea/go-logging v0.0.0-20200401235223-7e979d0e0d02 h1:Ezh2FrKVTFWkL0UVYH7DLx89SvBy9c4SeiG7odG8Yok=
|
||||
github.com/dsoprea/go-logging v0.0.0-20200401235223-7e979d0e0d02/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
|
||||
github.com/dsoprea/go-png-image-structure v0.0.0-20200113231611-5ee8d5825a92 h1:D/wlE1zb04BwhLmSARC6kdzXHwrihmSinLn16dIdJt4=
|
||||
github.com/dsoprea/go-png-image-structure v0.0.0-20200113231611-5ee8d5825a92/go.mod h1:E2uyTIhMXw4weEZrqrz1vFPtXVXrmikgCFRkcDv4nSg=
|
||||
github.com/dsoprea/go-png-image-structure v0.0.0-20200402000326-c0fdb803026f h1:cuf7rjLGedkB0V4UcWmWMxDZGKNtCM0dGt1WTWsZXDQ=
|
||||
github.com/dsoprea/go-png-image-structure v0.0.0-20200402000326-c0fdb803026f/go.mod h1:wFgCouxC0gy+d+sre8HkLj+VeUWPr969zAOvQ9NGXJc=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200322154813-27f0b0d142d7 h1:DJhSHW0odJrW5wR9MU6ry5S+PsxuRXA165KFaiB+cZo=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200322154813-27f0b0d142d7/go.mod h1:xv8CVgDmI/Shx/X+EUXyXELVnH5lSRUYRija52OHq7E=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200322184706-df132586647c h1:LMZ1OpXrehc3ES8TAUUJo0UUHR+vZ5AHx5INrhSHdpM=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200322184706-df132586647c/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200412174200-5aee815e0920 h1:/sPqpPAmg/hrNrlW6EjFrKMQkiJ4888voMOG0uYHNec=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200412174200-5aee815e0920/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
|
||||
github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
|
@ -174,12 +160,8 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
|
|||
github.com/gorilla/mux v0.0.0-20170228224354-599cba5e7b61/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gosimple/slug v1.5.0 h1:AIIjgCjHcLpX8LzM2NpG4QGW9kUfqv0OLiFRfPv/H3E=
|
||||
github.com/gosimple/slug v1.5.0/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0=
|
||||
github.com/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs=
|
||||
github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20171020063731-82921fcf811d/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
|
@ -229,8 +211,6 @@ github.com/lib/pq v1.1.0 h1:/5u4a+KGJptBRqGzPvYQL9p0d/tPR4S31+Tnzj9lEO4=
|
|||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/machinebox/progress v0.2.0/go.mod h1:hl4FywxSjfmkmCrersGhmJH7KwuKl+Ueq9BXkOny+iE=
|
||||
|
@ -339,13 +319,9 @@ github.com/shopspring/decimal v0.0.0-20191130220710-360f2bc03045 h1:8CnFGhoe92Iz
|
|||
github.com/shopspring/decimal v0.0.0-20191130220710-360f2bc03045/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/simplereach/timeutils v1.2.0 h1:btgOAlu9RW6de2r2qQiONhjgxdAG7BL6je0G6J/yPnA=
|
||||
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
|
||||
github.com/sirupsen/logrus v0.0.0-20170323161349-3bcb09397d6d/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q=
|
||||
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
|
||||
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
||||
|
@ -356,8 +332,6 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
|
@ -368,10 +342,6 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H
|
|||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/studio-b12/gowebdav v0.0.0-20200303150724-9380631c29a1 h1:TPyHV/OgChqNcnYqCoCvIFjR9TU60gFXXBKnhOBzVEI=
|
||||
github.com/studio-b12/gowebdav v0.0.0-20200303150724-9380631c29a1/go.mod h1:gCcfDlA1Y7GqOaeEKw5l9dOGx1VLdc/HuQSlQAaZ30s=
|
||||
github.com/tensorflow/tensorflow v1.14.0 h1:g0W2+f/RybcvmrTjPLTwXkfr/BsDGUd8FKT6ZzojOMo=
|
||||
github.com/tensorflow/tensorflow v1.14.0/go.mod h1:itOSERT4trABok4UOoG+X4BoKds9F3rIsySdn+Lvu90=
|
||||
github.com/tensorflow/tensorflow v1.15.0 h1:ujwCjW4LRUwUp7YrAK+menE0GZkeJgkQT5FgdWNpVCk=
|
||||
github.com/tensorflow/tensorflow v1.15.0/go.mod h1:itOSERT4trABok4UOoG+X4BoKds9F3rIsySdn+Lvu90=
|
||||
github.com/tensorflow/tensorflow v1.15.2 h1:7/f/A664Tml/nRJg04+p3StcrsT53mkcvmxYHXI21Qo=
|
||||
github.com/tensorflow/tensorflow v1.15.2/go.mod h1:itOSERT4trABok4UOoG+X4BoKds9F3rIsySdn+Lvu90=
|
||||
github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc=
|
||||
|
@ -427,8 +397,6 @@ golang.org/x/crypto v0.0.0-20180503215945-1f94bef427e3/go.mod h1:6SG95UA2DQfeDnf
|
|||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
@ -456,8 +424,6 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8ou
|
|||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
@ -490,8 +456,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -502,8 +466,6 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
|
|||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138 h1:H3uGjxCR/6Ds0Mjgyp7LMK81+LvmbvWWEnJhzk1Pi9E=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c h1:KfpJVdWhuRqNk4XVXzjXf2KAV4TBEP77SYdFGjeGuIE=
|
||||
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200401192744-099440627f01 h1:ysQJ/fU6laLOZJseIeOqXl6Mo+lw5z6b7QHnmUKjW+k=
|
||||
golang.org/x/tools v0.0.0-20200401192744-099440627f01/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
|
@ -533,8 +495,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
|
|||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M=
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/internal/workers"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
@ -25,7 +25,7 @@ func GetAccounts(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.AccountSearch
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
@ -59,7 +59,7 @@ func GetAccount(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
id := ParseUint(c.Param("id"))
|
||||
|
||||
if m, err := q.AccountByID(id); err == nil {
|
||||
|
@ -81,7 +81,7 @@ func GetAccountDirs(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
id := ParseUint(c.Param("id"))
|
||||
|
||||
m, err := q.AccountByID(id)
|
||||
|
@ -114,7 +114,7 @@ func ShareWithAccount(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
id := ParseUint(c.Param("id"))
|
||||
|
||||
m, err := q.AccountByID(id)
|
||||
|
@ -143,7 +143,7 @@ func ShareWithAccount(router *gin.RouterGroup, conf *config.Config) {
|
|||
dstFileName := dst + "/" + file.ShareFileName()
|
||||
|
||||
fileShare := entity.NewFileShare(file.ID, m.ID, dstFileName)
|
||||
fileShare.FirstOrCreate(conf.Db())
|
||||
fileShare.FirstOrCreate()
|
||||
}
|
||||
|
||||
workers.StartShare(conf)
|
||||
|
@ -173,7 +173,7 @@ func CreateAccount(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
m, err := entity.CreateAccount(f, conf.Db())
|
||||
m, err := entity.CreateAccount(f)
|
||||
|
||||
log.Debugf("create account: %+v %+v", f, m)
|
||||
|
||||
|
@ -202,7 +202,7 @@ func UpdateAccount(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
id := ParseUint(c.Param("id"))
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
m, err := q.AccountByID(id)
|
||||
|
||||
|
@ -228,7 +228,7 @@ func UpdateAccount(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
// 3) Save model with values from form
|
||||
if err := m.Save(f, conf.Db()); err != nil {
|
||||
if err := m.Save(f); err != nil {
|
||||
log.Error(err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, ErrSaveFailed)
|
||||
return
|
||||
|
@ -259,7 +259,7 @@ func DeleteAccount(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := ParseUint(c.Param("id"))
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
m, err := q.AccountByID(id)
|
||||
|
||||
|
@ -268,7 +268,7 @@ func DeleteAccount(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := m.Delete(conf.Db()); err != nil {
|
||||
if err := m.Delete(); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, txt.UcFirst(err.Error()))
|
||||
return
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/internal/thumb"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
|
@ -35,7 +35,7 @@ func GetAlbums(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.AlbumSearch
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
@ -61,7 +61,7 @@ func GetAlbums(router *gin.RouterGroup, conf *config.Config) {
|
|||
func GetAlbum(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.GET("/albums/:uuid", func(c *gin.Context) {
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
m, err := q.AlbumByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
|
@ -88,7 +88,7 @@ func CreateAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
m := entity.NewAlbum(f.AlbumName)
|
||||
m.AlbumFavorite = f.AlbumFavorite
|
||||
|
||||
|
@ -118,9 +118,8 @@ func UpdateAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
db := conf.Db()
|
||||
uuid := c.Param("uuid")
|
||||
q := query.New(db)
|
||||
q := service.Query()
|
||||
|
||||
m, err := q.AlbumByUUID(uuid)
|
||||
|
||||
|
@ -143,7 +142,7 @@ func UpdateAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := m.Save(f, conf.Db()); err != nil {
|
||||
if err := m.Save(f); err != nil {
|
||||
log.Error(err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, ErrSaveFailed)
|
||||
return
|
||||
|
@ -167,7 +166,7 @@ func DeleteAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
m, err := q.AlbumByUUID(id)
|
||||
|
||||
|
@ -199,7 +198,7 @@ func LikeAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
album, err := q.AlbumByUUID(id)
|
||||
|
||||
|
@ -230,7 +229,7 @@ func DislikeAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
album, err := q.AlbumByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
|
@ -264,7 +263,7 @@ func AddPhotosToAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
uuid := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
a, err := q.AlbumByUUID(uuid)
|
||||
|
||||
if err != nil {
|
||||
|
@ -280,11 +279,10 @@ func AddPhotosToAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
db := conf.Db()
|
||||
var added []*entity.PhotoAlbum
|
||||
|
||||
for _, p := range photos {
|
||||
added = append(added, entity.NewPhotoAlbum(p.PhotoUUID, a.AlbumUUID).FirstOrCreate(db))
|
||||
added = append(added, entity.NewPhotoAlbum(p.PhotoUUID, a.AlbumUUID).FirstOrCreate())
|
||||
}
|
||||
|
||||
if len(added) == 1 {
|
||||
|
@ -320,7 +318,7 @@ func RemovePhotosFromAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
a, err := q.AlbumByUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
|
@ -345,7 +343,7 @@ func DownloadAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
router.GET("/albums/:uuid/download", func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
a, err := q.AlbumByUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
|
@ -446,7 +444,7 @@ func AlbumThumbnail(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
gc := conf.Cache()
|
||||
cacheKey := fmt.Sprintf("album-thumbnail:%s:%s", uuid, typeName)
|
||||
|
|
|
@ -7,11 +7,13 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
)
|
||||
|
||||
// NewApiTest returns new API test helper
|
||||
func NewApiTest() (app *gin.Engine, router *gin.RouterGroup, conf *config.Config) {
|
||||
conf = config.TestConfig()
|
||||
service.SetConfig(conf)
|
||||
gin.SetMode(gin.TestMode)
|
||||
app = gin.New()
|
||||
router = app.Group("/api/v1")
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"path"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -23,7 +23,7 @@ func GetDownload(router *gin.RouterGroup, conf *config.Config) {
|
|||
router.GET("/download/:hash", func(c *gin.Context) {
|
||||
fileHash := c.Param("hash")
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
f, err := q.FileByHash(fileHash)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
|
@ -21,7 +22,7 @@ func GetFile(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
p, err := q.FileByHash(c.Param("hash"))
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -24,7 +24,7 @@ func GetGeo(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.GeoSearch
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/internal/thumb"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
|
@ -29,7 +29,7 @@ func GetLabels(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.LabelSearch
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
@ -67,7 +67,7 @@ func UpdateLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
m, err := q.LabelByUUID(id)
|
||||
|
||||
|
@ -99,7 +99,7 @@ func LikeLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
label, err := q.LabelByUUID(id)
|
||||
|
||||
|
@ -135,7 +135,7 @@ func DislikeLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
label, err := q.LabelByUUID(id)
|
||||
|
||||
|
@ -180,7 +180,7 @@ func LabelThumbnail(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
gc := conf.Cache()
|
||||
cacheKey := fmt.Sprintf("label-thumbnail:%s:%s", labelUUID, typeName)
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -18,7 +18,7 @@ func GetMomentsTime(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
|
||||
result, err := q.GetMomentsTime()
|
||||
if err != nil {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
)
|
||||
|
||||
|
@ -25,7 +26,7 @@ func GetPhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
p, err := q.PreloadPhotoByUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
|
@ -74,7 +75,7 @@ func UpdatePhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
// 3) Save model with values from form
|
||||
if err := entity.SavePhotoForm(m, f, db, conf.GeoCodingApi()); err != nil {
|
||||
if err := entity.SavePhotoForm(m, f, conf.GeoCodingApi()); err != nil {
|
||||
log.Error(err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, ErrSaveFailed)
|
||||
return
|
||||
|
@ -101,7 +102,7 @@ func UpdatePhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
// uuid: string PhotoUUID as returned by the API
|
||||
func GetPhotoDownload(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.GET("/photos/:uuid/download", func(c *gin.Context) {
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
f, err := q.FileByPhotoUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
|
@ -141,7 +142,7 @@ func LikePhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
m, err := q.PhotoByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
|
@ -175,7 +176,7 @@ func DislikePhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
m, err := q.PhotoByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
|
@ -24,7 +25,7 @@ func AddPhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
m, err := q.PhotoByUUID(c.Param("uuid"))
|
||||
db := conf.Db()
|
||||
|
||||
|
@ -40,7 +41,7 @@ func AddPhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
lm := entity.NewLabel(f.LabelName, f.LabelPriority).FirstOrCreate(db)
|
||||
lm := entity.NewLabel(f.LabelName, f.LabelPriority).FirstOrCreate()
|
||||
|
||||
if lm.New && f.LabelPriority >= 0 {
|
||||
event.Publish("count.labels", event.Data{
|
||||
|
@ -48,7 +49,7 @@ func AddPhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
})
|
||||
}
|
||||
|
||||
plm := entity.NewPhotoLabel(m.ID, lm.ID, f.Uncertainty, "manual").FirstOrCreate(db)
|
||||
plm := entity.NewPhotoLabel(m.ID, lm.ID, f.Uncertainty, "manual").FirstOrCreate()
|
||||
|
||||
if plm.Uncertainty > f.Uncertainty {
|
||||
plm.Uncertainty = f.Uncertainty
|
||||
|
@ -68,7 +69,7 @@ func AddPhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := p.Save(db); err != nil {
|
||||
if err := p.Save(); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
@ -130,7 +131,7 @@ func RemovePhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := p.Save(db); err != nil {
|
||||
if err := p.Save(); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
@ -185,7 +186,7 @@ func UpdatePhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := label.Save(db); err != nil {
|
||||
if err := label.Save(); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ func UpdatePhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := p.Save(db); err != nil {
|
||||
if err := p.Save(); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -36,7 +36,7 @@ func GetPhotos(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.PhotoSearch
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/internal/thumb"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
)
|
||||
|
@ -45,7 +45,7 @@ func GetPreview(router *gin.RouterGroup, conf *config.Config) {
|
|||
f.Count = 12
|
||||
f.Order = "relevance"
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
p, _, err := q.Photos(f)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/service"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
|
@ -47,7 +47,7 @@ func CreateZip(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
q := service.Query()
|
||||
files, err := q.FilesByUUID(f.Photos, 1000, 0)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -43,7 +43,7 @@ func copyAction(ctx *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
conf.MigrateDb()
|
||||
conf.InitDb()
|
||||
|
||||
// get cli first argument
|
||||
sourcePath := strings.TrimSpace(ctx.Args().First())
|
||||
|
|
|
@ -43,7 +43,7 @@ func importAction(ctx *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
conf.MigrateDb()
|
||||
conf.InitDb()
|
||||
|
||||
// get cli first argument
|
||||
sourcePath := strings.TrimSpace(ctx.Args().First())
|
||||
|
|
|
@ -42,7 +42,7 @@ func indexAction(ctx *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
conf.MigrateDb()
|
||||
conf.InitDb()
|
||||
log.Infof("indexing photos in %s", conf.OriginalsPath())
|
||||
|
||||
if conf.ReadOnly() {
|
||||
|
|
|
@ -28,7 +28,7 @@ func migrateAction(ctx *cli.Context) error {
|
|||
|
||||
log.Infoln("migrating database")
|
||||
|
||||
conf.MigrateDb()
|
||||
conf.InitDb()
|
||||
|
||||
elapsed := time.Since(start)
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ func startAction(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
// initialize the database
|
||||
conf.MigrateDb()
|
||||
conf.InitDb()
|
||||
|
||||
// check if daemon is running, if not initialize the daemon
|
||||
dctx := new(daemon.Context)
|
||||
|
|
|
@ -36,7 +36,7 @@ func (c *Config) DatabaseDsn() string {
|
|||
// Db returns the db connection.
|
||||
func (c *Config) Db() *gorm.DB {
|
||||
if c.db == nil {
|
||||
log.Fatal("config: database not initialised")
|
||||
log.Fatal("config: database not connected")
|
||||
}
|
||||
|
||||
return c.db
|
||||
|
@ -55,16 +55,15 @@ func (c *Config) CloseDb() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// MigrateDb will start a migration process.
|
||||
func (c *Config) MigrateDb() {
|
||||
db := c.Db()
|
||||
entity.Migrate(db)
|
||||
// InitDb will initialize the database connection and schema.
|
||||
func (c *Config) InitDb() {
|
||||
entity.SetDbProvider(c)
|
||||
entity.Migrate()
|
||||
}
|
||||
|
||||
// DropTables drops all tables in the currently configured database (be careful!).
|
||||
func (c *Config) DropTables() {
|
||||
db := c.Db()
|
||||
entity.DropTables(db)
|
||||
entity.DropTables(c.Db())
|
||||
}
|
||||
|
||||
// connectToDatabase establishes a database connection.
|
||||
|
@ -99,11 +98,11 @@ func (c *Config) connectToDatabase(ctx context.Context) error {
|
|||
log.Infof("starting database server at %s:%d\n", c.TidbServerHost(), c.TidbServerPort())
|
||||
|
||||
go tidb.Start(ctx, c.TidbServerPath(), c.TidbServerPort(), c.TidbServerHost(), c.Debug())
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
|
||||
for i := 1; i <= 12; i++ {
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
db, err = gorm.Open(dbDriver, dbDsn)
|
||||
|
||||
if db != nil && err == nil {
|
||||
|
@ -119,6 +118,8 @@ func (c *Config) connectToDatabase(ctx context.Context) error {
|
|||
initSuccess = true
|
||||
}
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
if err != nil || db == nil {
|
||||
|
|
|
@ -108,12 +108,12 @@ func NewTestConfig() *Config {
|
|||
// Make sure changes have been written to disk.
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
|
||||
c.MigrateDb()
|
||||
c.InitDb()
|
||||
|
||||
// Make sure changes have been written to disk.
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
|
||||
entity.CreateTestFixtures(c.Db())
|
||||
entity.CreateTestFixtures()
|
||||
|
||||
// TODO: Remove when new test fixtures are ready
|
||||
c.ImportSQL(c.ExamplesPath() + "/fixtures.sql")
|
||||
|
@ -134,7 +134,7 @@ func NewTestErrorConfig() *Config {
|
|||
log.Fatalf("config: %s", err.Error())
|
||||
}
|
||||
|
||||
c.MigrateDb()
|
||||
c.InitDb()
|
||||
return c
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/remote"
|
||||
"github.com/photoprism/photoprism/internal/remote/webdav"
|
||||
|
@ -52,7 +51,7 @@ type Account struct {
|
|||
}
|
||||
|
||||
// CreateAccount creates a new account entity in the database.
|
||||
func CreateAccount(form form.Account, db *gorm.DB) (model *Account, err error) {
|
||||
func CreateAccount(form form.Account) (model *Account, err error) {
|
||||
model = &Account{
|
||||
ShareSize: "",
|
||||
ShareExpires: 0,
|
||||
|
@ -60,13 +59,15 @@ func CreateAccount(form form.Account, db *gorm.DB) (model *Account, err error) {
|
|||
SyncStatus: AccountSyncStatusRefresh,
|
||||
}
|
||||
|
||||
err = model.Save(form, db)
|
||||
err = model.Save(form)
|
||||
|
||||
return model, err
|
||||
}
|
||||
|
||||
// Save updates the entity using form data and stores it in the database.
|
||||
func (m *Account) Save(form form.Account, db *gorm.DB) error {
|
||||
func (m *Account) Save(form form.Account) error {
|
||||
db := Db()
|
||||
|
||||
if err := deepcopier.Copy(m).From(form); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -95,8 +96,8 @@ func (m *Account) Save(form form.Account, db *gorm.DB) error {
|
|||
}
|
||||
|
||||
// Delete deletes the entity from the database.
|
||||
func (m *Account) Delete(db *gorm.DB) error {
|
||||
return db.Delete(m).Error
|
||||
func (m *Account) Delete() error {
|
||||
return Db().Delete(m).Error
|
||||
}
|
||||
|
||||
// Directories returns a list of directories or albums in an account.
|
||||
|
|
|
@ -73,7 +73,7 @@ func (m *Album) SetName(name string) {
|
|||
}
|
||||
|
||||
// Save updates the entity using form data and stores it in the database.
|
||||
func (m *Album) Save(f form.Album, db *gorm.DB) error {
|
||||
func (m *Album) Save(f form.Album) error {
|
||||
if err := deepcopier.Copy(m).From(f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -82,5 +82,5 @@ func (m *Album) Save(f form.Album, db *gorm.DB) error {
|
|||
m.SetName(f.AlbumName)
|
||||
}
|
||||
|
||||
return db.Save(m).Error
|
||||
return Db().Save(m).Error
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gosimple/slug"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
|
@ -32,8 +30,8 @@ var UnknownCamera = Camera{
|
|||
}
|
||||
|
||||
// CreateUnknownCamera initializes the database with an unknown camera if not exists
|
||||
func CreateUnknownCamera(db *gorm.DB) {
|
||||
UnknownCamera.FirstOrCreate(db)
|
||||
func CreateUnknownCamera() {
|
||||
UnknownCamera.FirstOrCreate()
|
||||
}
|
||||
|
||||
// NewCamera creates a camera entity from a model name and a make name.
|
||||
|
@ -64,10 +62,9 @@ func NewCamera(modelName string, makeName string) *Camera {
|
|||
return result
|
||||
}
|
||||
|
||||
// FirstOrCreate checks wether the camera model exist already in the database
|
||||
func (m *Camera) FirstOrCreate(db *gorm.DB) *Camera {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
// FirstOrCreate checks if the camera model exist already in the database
|
||||
func (m *Camera) FirstOrCreate() *Camera {
|
||||
db := Db()
|
||||
|
||||
if err := db.FirstOrCreate(m, "camera_model = ? AND camera_make = ?", m.CameraModel, m.CameraMake).Error; err != nil {
|
||||
log.Errorf("camera: %s", err)
|
||||
|
|
|
@ -6,6 +6,14 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCamera_FirstOrCreate(t *testing.T) {
|
||||
t.Run("iphone-se", func(t *testing.T) {
|
||||
camera := NewCamera("iPhone SE", "Apple")
|
||||
camera.FirstOrCreate()
|
||||
assert.GreaterOrEqual(t, camera.ID, uint(1))
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewCamera(t *testing.T) {
|
||||
t.Run("unknown camera", func(t *testing.T) {
|
||||
camera := NewCamera("", "Nikon")
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"github.com/gosimple/slug"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/maps"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
// altCountryNames defines mapping between different names for the same countriy
|
||||
|
@ -34,8 +33,8 @@ var UnknownCountry = Country{
|
|||
}
|
||||
|
||||
// CreateUnknownCountry is used to initialize the database with the default country
|
||||
func CreateUnknownCountry(db *gorm.DB) {
|
||||
UnknownCountry.FirstOrCreate(db)
|
||||
func CreateUnknownCountry() {
|
||||
UnknownCountry.FirstOrCreate()
|
||||
}
|
||||
|
||||
// NewCountry creates a new country, with default country code if not provided
|
||||
|
@ -59,12 +58,9 @@ func NewCountry(countryCode string, countryName string) *Country {
|
|||
return result
|
||||
}
|
||||
|
||||
// FirstOrCreate checks wether the country exist already in the database (using countryCode)
|
||||
func (m *Country) FirstOrCreate(db *gorm.DB) *Country {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "id = ?", m.ID).Error; err != nil {
|
||||
// FirstOrCreate checks if the country exist already in the database (using countryCode)
|
||||
func (m *Country) FirstOrCreate() *Country {
|
||||
if err := Db().FirstOrCreate(m, "id = ?", m.ID).Error; err != nil {
|
||||
log.Errorf("country: %s", err)
|
||||
}
|
||||
|
||||
|
|
89
internal/entity/db.go
Normal file
89
internal/entity/db.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
)
|
||||
|
||||
var dbProvider DbProvider
|
||||
|
||||
type DbProvider interface {
|
||||
Db() *gorm.DB
|
||||
}
|
||||
|
||||
// SetDbProvider sets the provider to get a gorm db connection.
|
||||
func SetDbProvider(provider DbProvider) {
|
||||
dbProvider = provider
|
||||
}
|
||||
|
||||
// Db() returns a database connection.
|
||||
func Db() *gorm.DB {
|
||||
return dbProvider.Db()
|
||||
}
|
||||
|
||||
// Db() returns an unscoped database connection.
|
||||
func Unscoped() *gorm.DB {
|
||||
return Db().Unscoped()
|
||||
}
|
||||
|
||||
type Gorm struct {
|
||||
Driver string
|
||||
Dsn string
|
||||
|
||||
once sync.Once
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// Db returns the gorm db connection.
|
||||
func (g *Gorm) Db() *gorm.DB {
|
||||
g.once.Do(g.Connect)
|
||||
|
||||
if g.db == nil {
|
||||
log.Fatal("entity: database not connected")
|
||||
}
|
||||
|
||||
return g.db
|
||||
}
|
||||
|
||||
// Connect creates a new gorm db connection.
|
||||
func (g *Gorm) Connect() {
|
||||
db, err := gorm.Open(g.Driver, g.Dsn)
|
||||
|
||||
if err != nil || db == nil {
|
||||
for i := 1; i <= 12; i++ {
|
||||
fmt.Printf("gorm.Open(%s, %s) %d\n", g.Driver, g.Dsn, i)
|
||||
db, err = gorm.Open(g.Driver, g.Dsn)
|
||||
|
||||
if db != nil && err == nil {
|
||||
break
|
||||
} else {
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil || db == nil {
|
||||
fmt.Println(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
db.LogMode(false)
|
||||
db.SetLogger(log)
|
||||
|
||||
g.db = db
|
||||
}
|
||||
|
||||
// Close closes the gorm db connection.
|
||||
func (g *Gorm) Close() {
|
||||
if g.db != nil {
|
||||
if err := g.db.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
g.db = nil
|
||||
}
|
||||
}
|
|
@ -1,10 +1,5 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
// Description stores additional metadata fields for each photo to improve search performance.
|
||||
type Description struct {
|
||||
PhotoID uint `gorm:"primary_key;auto_increment:false"`
|
||||
|
@ -18,11 +13,8 @@ type Description struct {
|
|||
}
|
||||
|
||||
// FirstOrCreate returns the matching entity or creates a new one.
|
||||
func (m *Description) FirstOrCreate(db *gorm.DB) error {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
return db.FirstOrCreate(m, "photo_id = ?", m.PhotoID).Error
|
||||
func (m *Description) FirstOrCreate() error {
|
||||
return Db().FirstOrCreate(m, "photo_id = ?", m.PhotoID).Error
|
||||
}
|
||||
|
||||
// NoDescription checks if the photo has no Description
|
||||
|
|
|
@ -23,8 +23,8 @@ func logError(result *gorm.DB) {
|
|||
}
|
||||
|
||||
// Migrate creates all tables and inserts default entities as needed.
|
||||
func Migrate(db *gorm.DB) {
|
||||
db.AutoMigrate(
|
||||
func Migrate() {
|
||||
Db().AutoMigrate(
|
||||
&Account{},
|
||||
&File{},
|
||||
&FileShare{},
|
||||
|
@ -46,10 +46,10 @@ func Migrate(db *gorm.DB) {
|
|||
&Link{},
|
||||
)
|
||||
|
||||
CreateUnknownPlace(db)
|
||||
CreateUnknownCountry(db)
|
||||
CreateUnknownCamera(db)
|
||||
CreateUnknownLens(db)
|
||||
CreateUnknownPlace()
|
||||
CreateUnknownCountry()
|
||||
CreateUnknownCamera()
|
||||
CreateUnknownLens()
|
||||
}
|
||||
|
||||
// DropTables drops database tables for all known entities.
|
||||
|
|
|
@ -14,6 +14,18 @@ func TestMain(m *testing.M) {
|
|||
log = logrus.StandardLogger()
|
||||
log.Out = &logBuffer
|
||||
log.SetLevel(logrus.DebugLevel)
|
||||
|
||||
db := &Gorm{
|
||||
Driver: "mysql",
|
||||
Dsn: "photoprism:photoprism@tcp(photoprism-db:4001)/photoprism?parseTime=true",
|
||||
}
|
||||
|
||||
SetDbProvider(db)
|
||||
Migrate()
|
||||
|
||||
code := m.Run()
|
||||
|
||||
db.Close()
|
||||
|
||||
os.Exit(code)
|
||||
}
|
||||
|
|
|
@ -52,10 +52,10 @@ type File struct {
|
|||
}
|
||||
|
||||
// FirstFileByHash gets a file in db from its hash
|
||||
func FirstFileByHash(db *gorm.DB, fileHash string) (File, error) {
|
||||
func FirstFileByHash(fileHash string) (File, error) {
|
||||
var file File
|
||||
|
||||
q := db.Unscoped().First(&file, "file_hash = ?", fileHash)
|
||||
q := Db().Unscoped().First(&file, "file_hash = ?", fileHash)
|
||||
|
||||
return file, q.Error
|
||||
}
|
||||
|
|
|
@ -2,9 +2,6 @@ package entity
|
|||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -48,11 +45,8 @@ func NewFileShare(fileID, accountID uint, remoteName string) *FileShare {
|
|||
}
|
||||
|
||||
// FirstOrCreate returns the matching entity or creates a new one.
|
||||
func (m *FileShare) FirstOrCreate(db *gorm.DB) *FileShare {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "file_id = ? AND account_id = ? AND remote_name = ?", m.FileID, m.AccountID, m.RemoteName).Error; err != nil {
|
||||
func (m *FileShare) FirstOrCreate() *FileShare {
|
||||
if err := Db().FirstOrCreate(m, "file_id = ? AND account_id = ? AND remote_name = ?", m.FileID, m.AccountID, m.RemoteName).Error; err != nil {
|
||||
log.Errorf("file push: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,6 @@ package entity
|
|||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -48,11 +45,8 @@ func NewFileSync(accountID uint, remoteName string) *FileSync {
|
|||
}
|
||||
|
||||
// FirstOrCreate returns the matching entity or creates a new one.
|
||||
func (m *FileSync) FirstOrCreate(db *gorm.DB) *FileSync {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "account_id = ? AND remote_name = ?", m.AccountID, m.RemoteName).Error; err != nil {
|
||||
func (m *FileSync) FirstOrCreate() *FileSync {
|
||||
if err := Db().FirstOrCreate(m, "account_id = ? AND remote_name = ?", m.AccountID, m.RemoteName).Error; err != nil {
|
||||
log.Errorf("file sync: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
// CreateTestFixtures inserts all known entities into the database for testing.
|
||||
func CreateTestFixtures(db *gorm.DB) {
|
||||
CreateLabelFixtures(db)
|
||||
func CreateTestFixtures() {
|
||||
CreateLabelFixtures()
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package entity
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
|
@ -26,12 +24,9 @@ func NewKeyword(keyword string) *Keyword {
|
|||
return result
|
||||
}
|
||||
|
||||
// FirstOrCreate checks wether the keyword already exist in the database
|
||||
func (m *Keyword) FirstOrCreate(db *gorm.DB) *Keyword {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "keyword = ?", m.Keyword).Error; err != nil {
|
||||
// FirstOrCreate checks if the keyword already exist in the database
|
||||
func (m *Keyword) FirstOrCreate() *Keyword {
|
||||
if err := Db().FirstOrCreate(m, "keyword = ?", m.Keyword).Error; err != nil {
|
||||
log.Errorf("keyword: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/gosimple/slug"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/classify"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
@ -62,11 +61,8 @@ func NewLabel(name string, priority int) *Label {
|
|||
}
|
||||
|
||||
// FirstOrCreate checks if the label already exists in the database
|
||||
func (m *Label) FirstOrCreate(db *gorm.DB) *Label {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "label_slug = ? OR custom_slug = ?", m.LabelSlug, m.CustomSlug).Error; err != nil {
|
||||
func (m *Label) FirstOrCreate() *Label {
|
||||
if err := Db().FirstOrCreate(m, "label_slug = ? OR custom_slug = ?", m.LabelSlug, m.CustomSlug).Error; err != nil {
|
||||
log.Errorf("label: %s", err)
|
||||
}
|
||||
|
||||
|
@ -91,8 +87,9 @@ func (m *Label) SetName(name string) {
|
|||
}
|
||||
|
||||
// Updates a label if necessary
|
||||
func (m *Label) Update(label classify.Label, db *gorm.DB) error {
|
||||
func (m *Label) Update(label classify.Label) error {
|
||||
save := false
|
||||
db := Db()
|
||||
|
||||
if m.LabelPriority != label.Priority {
|
||||
m.LabelPriority = label.Priority
|
||||
|
@ -120,7 +117,7 @@ func (m *Label) Update(label classify.Label, db *gorm.DB) error {
|
|||
|
||||
// Add categories
|
||||
for _, category := range label.Categories {
|
||||
sn := NewLabel(txt.Title(category), -3).FirstOrCreate(db)
|
||||
sn := NewLabel(txt.Title(category), -3).FirstOrCreate()
|
||||
if err := db.Model(m).Association("LabelCategories").Append(sn).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ package entity
|
|||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
var LabelFixtures = map[string]Label{
|
||||
|
@ -27,8 +25,8 @@ var LabelFixtures = map[string]Label{
|
|||
}
|
||||
|
||||
// CreateLabelFixtures inserts known entities into the database for testing.
|
||||
func CreateLabelFixtures(db *gorm.DB) {
|
||||
func CreateLabelFixtures() {
|
||||
for _, entity := range LabelFixtures {
|
||||
db.Create(&entity)
|
||||
Db().Create(&entity)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gosimple/slug"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
// Lens represents camera lens (as extracted from UpdateExif metadata)
|
||||
|
@ -31,8 +29,8 @@ var UnknownLens = Lens{
|
|||
}
|
||||
|
||||
// CreateUnknownLens initializes the database with an unknown lens if not exists
|
||||
func CreateUnknownLens(db *gorm.DB) {
|
||||
UnknownLens.FirstOrCreate(db)
|
||||
func CreateUnknownLens() {
|
||||
UnknownLens.FirstOrCreate()
|
||||
}
|
||||
|
||||
// TableName returns Lens table identifier "lens"
|
||||
|
@ -60,11 +58,8 @@ func NewLens(modelName string, makeName string) *Lens {
|
|||
}
|
||||
|
||||
// FirstOrCreate checks if the lens already exists in the database
|
||||
func (m *Lens) FirstOrCreate(db *gorm.DB) *Lens {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "lens_slug = ?", m.LensSlug).Error; err != nil {
|
||||
func (m *Lens) FirstOrCreate() *Lens {
|
||||
if err := Db().FirstOrCreate(m, "lens_slug = ?", m.LensSlug).Error; err != nil {
|
||||
log.Errorf("lens: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/maps"
|
||||
"github.com/photoprism/photoprism/pkg/s2"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
|
@ -32,7 +31,9 @@ func NewLocation(lat, lng float32) *Location {
|
|||
}
|
||||
|
||||
// Find gets the location using either the db or the api if not in the db
|
||||
func (m *Location) Find(db *gorm.DB, api string) error {
|
||||
func (m *Location) Find(api string) error {
|
||||
db := Db()
|
||||
|
||||
if err := db.Preload("Place").First(m, "id = ?", m.ID).Error; err == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -45,7 +46,7 @@ func (m *Location) Find(db *gorm.DB, api string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if place := FindPlaceByLabel(l.S2Token(), l.Label(), db); place != nil {
|
||||
if place := FindPlaceByLabel(l.S2Token(), l.Label()); place != nil {
|
||||
m.Place = place
|
||||
} else {
|
||||
m.Place = &Place{
|
||||
|
|
|
@ -67,7 +67,8 @@ type Photo struct {
|
|||
}
|
||||
|
||||
// SavePhotoForm updates a model using form data and persists it in the database.
|
||||
func SavePhotoForm(model Photo, form form.Photo, db *gorm.DB, geoApi string) error {
|
||||
func SavePhotoForm(model Photo, form form.Photo, geoApi string) error {
|
||||
db := Db()
|
||||
locChanged := model.PhotoLat != form.PhotoLat || model.PhotoLng != form.PhotoLng
|
||||
|
||||
if err := deepcopier.Copy(&model).From(form); err != nil {
|
||||
|
@ -83,9 +84,9 @@ func SavePhotoForm(model Photo, form form.Photo, db *gorm.DB, geoApi string) err
|
|||
}
|
||||
|
||||
if model.HasLatLng() && locChanged && model.LocationSrc == SrcManual {
|
||||
locKeywords, labels := model.UpdateLocation(db, geoApi)
|
||||
locKeywords, labels := model.UpdateLocation(geoApi)
|
||||
|
||||
model.AddLabels(labels, db)
|
||||
model.AddLabels(labels)
|
||||
|
||||
w := txt.UniqueKeywords(model.Description.PhotoKeywords)
|
||||
w = append(w, locKeywords...)
|
||||
|
@ -97,7 +98,7 @@ func SavePhotoForm(model Photo, form form.Photo, db *gorm.DB, geoApi string) err
|
|||
log.Warnf("%s (%s)", err.Error(), model.PhotoUUID)
|
||||
}
|
||||
|
||||
if err := model.IndexKeywords(db); err != nil {
|
||||
if err := model.IndexKeywords(); err != nil {
|
||||
log.Warnf("%s (%s)", err.Error(), model.PhotoUUID)
|
||||
}
|
||||
|
||||
|
@ -109,7 +110,8 @@ func SavePhotoForm(model Photo, form form.Photo, db *gorm.DB, geoApi string) err
|
|||
}
|
||||
|
||||
// Save stored the entity in the database.
|
||||
func (m *Photo) Save(db *gorm.DB) error {
|
||||
func (m *Photo) Save() error {
|
||||
db := Db()
|
||||
labels := m.ClassifyLabels()
|
||||
|
||||
if err := m.UpdateTitle(labels); err != nil {
|
||||
|
@ -122,7 +124,7 @@ func (m *Photo) Save(db *gorm.DB) error {
|
|||
m.Description.PhotoKeywords = strings.Join(txt.UniqueWords(w), ", ")
|
||||
}
|
||||
|
||||
if err := m.IndexKeywords(db); err != nil {
|
||||
if err := m.IndexKeywords(); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
|
@ -181,11 +183,13 @@ func (m *Photo) BeforeSave(scope *gorm.Scope) error {
|
|||
}
|
||||
|
||||
// IndexKeywords adds given keywords to the photo entry
|
||||
func (m *Photo) IndexKeywords(db *gorm.DB) error {
|
||||
func (m *Photo) IndexKeywords() error {
|
||||
if !m.DescriptionLoaded() {
|
||||
return fmt.Errorf("photo: can't index keywords, description not loaded (%s)", m.PhotoUUID)
|
||||
}
|
||||
|
||||
db := Db()
|
||||
|
||||
var keywordIds []uint
|
||||
var keywords []string
|
||||
|
||||
|
@ -199,7 +203,7 @@ func (m *Photo) IndexKeywords(db *gorm.DB) error {
|
|||
keywords = txt.UniqueWords(keywords)
|
||||
|
||||
for _, w := range keywords {
|
||||
kw := NewKeyword(w).FirstOrCreate(db)
|
||||
kw := NewKeyword(w).FirstOrCreate()
|
||||
|
||||
if kw.Skip {
|
||||
continue
|
||||
|
@ -207,15 +211,15 @@ func (m *Photo) IndexKeywords(db *gorm.DB) error {
|
|||
|
||||
keywordIds = append(keywordIds, kw.ID)
|
||||
|
||||
NewPhotoKeyword(m.ID, kw.ID).FirstOrCreate(db)
|
||||
NewPhotoKeyword(m.ID, kw.ID).FirstOrCreate()
|
||||
}
|
||||
|
||||
return db.Where("photo_id = ? AND keyword_id NOT IN (?)", m.ID, keywordIds).Delete(&PhotoKeyword{}).Error
|
||||
}
|
||||
|
||||
// PreloadFiles prepares gorm scope to retrieve photo file
|
||||
func (m *Photo) PreloadFiles(db *gorm.DB) {
|
||||
q := db.NewScope(nil).DB().
|
||||
func (m *Photo) PreloadFiles() {
|
||||
q := Db().NewScope(nil).DB().
|
||||
Table("files").
|
||||
Select(`files.*`).
|
||||
Where("files.photo_id = ?", m.ID).
|
||||
|
@ -224,8 +228,8 @@ func (m *Photo) PreloadFiles(db *gorm.DB) {
|
|||
logError(q.Scan(&m.Files))
|
||||
}
|
||||
|
||||
/* func (m *Photo) PreloadLabels(db *gorm.DB) {
|
||||
q := db.NewScope(nil).DB().
|
||||
/* func (m *Photo) PreloadLabels() {
|
||||
q := Db().NewScope(nil).DB().
|
||||
Table("labels").
|
||||
Select(`labels.*`).
|
||||
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = ?", m.ID).
|
||||
|
@ -236,8 +240,8 @@ func (m *Photo) PreloadFiles(db *gorm.DB) {
|
|||
} */
|
||||
|
||||
// PreloadKeywords prepares gorm scope to retrieve photo keywords
|
||||
func (m *Photo) PreloadKeywords(db *gorm.DB) {
|
||||
q := db.NewScope(nil).DB().
|
||||
func (m *Photo) PreloadKeywords() {
|
||||
q := Db().NewScope(nil).DB().
|
||||
Table("keywords").
|
||||
Select(`keywords.*`).
|
||||
Joins("JOIN photos_keywords ON photos_keywords.keyword_id = keywords.id AND photos_keywords.photo_id = ?", m.ID).
|
||||
|
@ -247,8 +251,8 @@ func (m *Photo) PreloadKeywords(db *gorm.DB) {
|
|||
}
|
||||
|
||||
// PreloadAlbums prepares gorm scope to retrieve photo albums
|
||||
func (m *Photo) PreloadAlbums(db *gorm.DB) {
|
||||
q := db.NewScope(nil).DB().
|
||||
func (m *Photo) PreloadAlbums() {
|
||||
q := Db().NewScope(nil).DB().
|
||||
Table("albums").
|
||||
Select(`albums.*`).
|
||||
Joins("JOIN photos_albums ON photos_albums.album_uuid = albums.album_uuid AND photos_albums.photo_uuid = ?", m.PhotoUUID).
|
||||
|
@ -259,11 +263,11 @@ func (m *Photo) PreloadAlbums(db *gorm.DB) {
|
|||
}
|
||||
|
||||
// PreloadMany prepares gorm scope to retrieve photo file, albums and keywords
|
||||
func (m *Photo) PreloadMany(db *gorm.DB) {
|
||||
m.PreloadFiles(db)
|
||||
// m.PreloadLabels(db)
|
||||
m.PreloadKeywords(db)
|
||||
m.PreloadAlbums(db)
|
||||
func (m *Photo) PreloadMany() {
|
||||
m.PreloadFiles()
|
||||
// m.PreloadLabels()
|
||||
m.PreloadKeywords()
|
||||
m.PreloadAlbums()
|
||||
}
|
||||
|
||||
// NoLocation checks if the photo has no location
|
||||
|
@ -369,10 +373,12 @@ func (m *Photo) UpdateTitle(labels classify.Labels) error {
|
|||
}
|
||||
|
||||
// AddLabels updates the entity with additional or updated label information.
|
||||
func (m *Photo) AddLabels(labels classify.Labels, db *gorm.DB) {
|
||||
func (m *Photo) AddLabels(labels classify.Labels) {
|
||||
db := Db()
|
||||
|
||||
// TODO: Update classify labels from database
|
||||
for _, label := range labels {
|
||||
lm := NewLabel(label.Title(), label.Priority).FirstOrCreate(db)
|
||||
lm := NewLabel(label.Title(), label.Priority).FirstOrCreate()
|
||||
|
||||
if lm.New {
|
||||
event.EntitiesCreated("labels", []*Label{lm})
|
||||
|
@ -384,11 +390,11 @@ func (m *Photo) AddLabels(labels classify.Labels, db *gorm.DB) {
|
|||
}
|
||||
}
|
||||
|
||||
if err := lm.Update(label, db); err != nil {
|
||||
if err := lm.Update(label); err != nil {
|
||||
log.Errorf("index: %s", err)
|
||||
}
|
||||
|
||||
plm := NewPhotoLabel(m.ID, lm.ID, label.Uncertainty, label.Source).FirstOrCreate(db)
|
||||
plm := NewPhotoLabel(m.ID, lm.ID, label.Uncertainty, label.Source).FirstOrCreate()
|
||||
|
||||
if plm.Uncertainty > label.Uncertainty && plm.Uncertainty > 100 {
|
||||
plm.Uncertainty = label.Uncertainty
|
||||
|
|
|
@ -2,9 +2,6 @@ package entity
|
|||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
// PhotoAlbum represents the many_to_many relation between Photo and Album
|
||||
|
@ -33,12 +30,9 @@ func NewPhotoAlbum(photoUUID, albumUUID string) *PhotoAlbum {
|
|||
return result
|
||||
}
|
||||
|
||||
// FirstOrCreate checks wether the PhotoAlbum relation already exist in the database before the creation
|
||||
func (m *PhotoAlbum) FirstOrCreate(db *gorm.DB) *PhotoAlbum {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "photo_uuid = ? AND album_uuid = ?", m.PhotoUUID, m.AlbumUUID).Error; err != nil {
|
||||
// FirstOrCreate checks if the PhotoAlbum relation already exist in the database before the creation
|
||||
func (m *PhotoAlbum) FirstOrCreate() *PhotoAlbum {
|
||||
if err := Db().FirstOrCreate(m, "photo_uuid = ? AND album_uuid = ?", m.PhotoUUID, m.AlbumUUID).Error; err != nil {
|
||||
log.Errorf("photo album: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
// PhotoKeyword represents the many-to-many relation between Photo and Keyword
|
||||
type PhotoKeyword struct {
|
||||
PhotoID uint `gorm:"primary_key;auto_increment:false"`
|
||||
|
@ -26,12 +21,9 @@ func NewPhotoKeyword(photoID, keywordID uint) *PhotoKeyword {
|
|||
return result
|
||||
}
|
||||
|
||||
// FirstOrCreate checks wether the PhotoKeywords relation already exist in the database before the creation
|
||||
func (m *PhotoKeyword) FirstOrCreate(db *gorm.DB) *PhotoKeyword {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "photo_id = ? AND keyword_id = ?", m.PhotoID, m.KeywordID).Error; err != nil {
|
||||
// FirstOrCreate checks if the PhotoKeywords relation already exist in the database before the creation
|
||||
func (m *PhotoKeyword) FirstOrCreate() *PhotoKeyword {
|
||||
if err := Db().FirstOrCreate(m, "photo_id = ? AND keyword_id = ?", m.PhotoID, m.KeywordID).Error; err != nil {
|
||||
log.Errorf("photo keyword: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/classify"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
// PhotoLabel represents the many-to-many relation between Photo and label.
|
||||
|
@ -35,11 +33,8 @@ func NewPhotoLabel(photoID, labelID uint, uncertainty int, source string) *Photo
|
|||
}
|
||||
|
||||
// FirstOrCreate checks if the PhotoLabel relation already exist in the database before the creation
|
||||
func (m *PhotoLabel) FirstOrCreate(db *gorm.DB) *PhotoLabel {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "photo_id = ? AND label_id = ?", m.PhotoID, m.LabelID).Error; err != nil {
|
||||
func (m *PhotoLabel) FirstOrCreate() *PhotoLabel {
|
||||
if err := Db().FirstOrCreate(m, "photo_id = ? AND label_id = ?", m.PhotoID, m.LabelID).Error; err != nil {
|
||||
log.Errorf("photo label: %s", err)
|
||||
}
|
||||
|
||||
|
@ -63,7 +58,7 @@ func (m *PhotoLabel) ClassifyLabel() classify.Label {
|
|||
}
|
||||
|
||||
// Save saves the entity in the database and returns an error.
|
||||
func (m *PhotoLabel) Save(db *gorm.DB) error {
|
||||
func (m *PhotoLabel) Save() error {
|
||||
if m.Photo != nil {
|
||||
m.Photo = nil
|
||||
}
|
||||
|
@ -72,5 +67,5 @@ func (m *PhotoLabel) Save(db *gorm.DB) error {
|
|||
m.Label.SetName(m.Label.LabelName)
|
||||
}
|
||||
|
||||
return db.Save(m).Error
|
||||
return Db().Save(m).Error
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package entity
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/classify"
|
||||
"github.com/photoprism/photoprism/internal/event"
|
||||
"gopkg.in/ugjka/go-tz.v2/tz"
|
||||
|
@ -43,10 +42,10 @@ func (m *Photo) GetTakenAt() time.Time {
|
|||
}
|
||||
|
||||
// UpdateLocation updates location and labels based on latitude and longitude.
|
||||
func (m *Photo) UpdateLocation(db *gorm.DB, geoApi string) (keywords []string, labels classify.Labels) {
|
||||
func (m *Photo) UpdateLocation(geoApi string) (keywords []string, labels classify.Labels) {
|
||||
var location = NewLocation(m.PhotoLat, m.PhotoLng)
|
||||
|
||||
err := location.Find(db, geoApi)
|
||||
err := location.Find(geoApi)
|
||||
|
||||
if err == nil {
|
||||
if location.Place.New {
|
||||
|
@ -66,7 +65,7 @@ func (m *Photo) UpdateLocation(db *gorm.DB, geoApi string) (keywords []string, l
|
|||
m.TakenAt = m.GetTakenAt()
|
||||
}
|
||||
|
||||
country := NewCountry(location.CountryCode(), location.CountryName()).FirstOrCreate(db)
|
||||
country := NewCountry(location.CountryCode(), location.CountryName()).FirstOrCreate()
|
||||
|
||||
if country.New {
|
||||
event.Publish("count.countries", event.Data{
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/maps"
|
||||
"github.com/photoprism/photoprism/internal/mutex"
|
||||
)
|
||||
|
||||
// Place used to associate photos to places
|
||||
|
@ -36,8 +35,8 @@ var UnknownPlace = Place{
|
|||
}
|
||||
|
||||
// CreateUnknownPlace initializes default place in the database
|
||||
func CreateUnknownPlace(db *gorm.DB) {
|
||||
UnknownPlace.FirstOrCreate(db)
|
||||
func CreateUnknownPlace() {
|
||||
UnknownPlace.FirstOrCreate()
|
||||
}
|
||||
|
||||
// AfterCreate sets the New column used for database callback
|
||||
|
@ -46,10 +45,10 @@ func (m *Place) AfterCreate(scope *gorm.Scope) error {
|
|||
}
|
||||
|
||||
// FindPlaceByLabel returns a place from an id or a label
|
||||
func FindPlaceByLabel(id string, label string, db *gorm.DB) *Place {
|
||||
func FindPlaceByLabel(id string, label string) *Place {
|
||||
place := &Place{}
|
||||
|
||||
if err := db.First(place, "id = ? OR loc_label = ?", id, label).Error; err != nil {
|
||||
if err := Db().First(place, "id = ? OR loc_label = ?", id, label).Error; err != nil {
|
||||
log.Debugf("place: %s for id %s or label \"%s\"", err.Error(), id, label)
|
||||
return nil
|
||||
}
|
||||
|
@ -58,20 +57,17 @@ func FindPlaceByLabel(id string, label string, db *gorm.DB) *Place {
|
|||
}
|
||||
|
||||
// Find returns db record of place
|
||||
func (m *Place) Find(db *gorm.DB) error {
|
||||
if err := db.First(m, "id = ?", m.ID).Error; err != nil {
|
||||
func (m *Place) Find() error {
|
||||
if err := Db().First(m, "id = ?", m.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FirstOrCreate checks wether the place already exists in the database
|
||||
func (m *Place) FirstOrCreate(db *gorm.DB) *Place {
|
||||
mutex.Db.Lock()
|
||||
defer mutex.Db.Unlock()
|
||||
|
||||
if err := db.FirstOrCreate(m, "id = ? OR loc_label = ?", m.ID, m.LocLabel).Error; err != nil {
|
||||
// FirstOrCreate checks if the place already exists in the database
|
||||
func (m *Place) FirstOrCreate() *Place {
|
||||
if err := Db().FirstOrCreate(m, "id = ? OR loc_label = ?", m.ID, m.LocLabel).Error; err != nil {
|
||||
log.Debugf("place: %s for token %s or label \"%s\"", err.Error(), m.ID, m.LocLabel)
|
||||
}
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ func (imp *Import) DestinationFilename(mainFile *MediaFile, mediaFile *MediaFile
|
|||
dateCreated := mainFile.DateCreated()
|
||||
|
||||
if !mediaFile.IsSidecar() {
|
||||
if f, err := entity.FirstFileByHash(imp.conf.Db(), mediaFile.Hash()); err == nil {
|
||||
if f, err := entity.FirstFileByHash(mediaFile.Hash()); err == nil {
|
||||
existingFilename := imp.conf.OriginalsPath() + string(os.PathSeparator) + f.FileName
|
||||
return existingFilename, fmt.Errorf("\"%s\" is identical to \"%s\" (%s)", mediaFile.FileName(), f.FileName, mediaFile.Hash())
|
||||
}
|
||||
|
|
|
@ -193,8 +193,8 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
|
||||
if photo.CameraSrc == entity.SrcAuto && (fileChanged || o.UpdateCamera) {
|
||||
// Set UpdateCamera, Lens, Focal Length and F Number
|
||||
photo.Camera = entity.NewCamera(m.CameraModel(), m.CameraMake()).FirstOrCreate(ind.db)
|
||||
photo.Lens = entity.NewLens(m.LensModel(), m.LensMake()).FirstOrCreate(ind.db)
|
||||
photo.Camera = entity.NewCamera(m.CameraModel(), m.CameraMake()).FirstOrCreate()
|
||||
photo.Lens = entity.NewLens(m.LensModel(), m.LensMake()).FirstOrCreate()
|
||||
photo.PhotoFocalLength = m.FocalLength()
|
||||
photo.PhotoFNumber = m.FNumber()
|
||||
photo.PhotoIso = m.Iso()
|
||||
|
@ -208,7 +208,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
if fileChanged || o.UpdateKeywords || o.UpdateLocation || o.UpdateTitle || photo.NoTitle() {
|
||||
if photo.HasLatLng() {
|
||||
var locLabels classify.Labels
|
||||
locKeywords, locLabels = photo.UpdateLocation(ind.db, ind.conf.GeoCodingApi())
|
||||
locKeywords, locLabels = photo.UpdateLocation(ind.conf.GeoCodingApi())
|
||||
labels = append(labels, locLabels...)
|
||||
} else {
|
||||
log.Info("index: no latitude and longitude in metadata")
|
||||
|
@ -326,7 +326,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
event.EntitiesCreated("photos", []entity.Photo{photo})
|
||||
}
|
||||
|
||||
photo.AddLabels(labels, ind.db)
|
||||
photo.AddLabels(labels)
|
||||
|
||||
file.PhotoID = photo.ID
|
||||
result.PhotoID = photo.ID
|
||||
|
@ -370,7 +370,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
return result
|
||||
}
|
||||
|
||||
if err := photo.IndexKeywords(ind.db); err != nil {
|
||||
if err := photo.IndexKeywords(); err != nil {
|
||||
log.Warnf("%s (%s)", err.Error(), photo.PhotoUUID)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -24,7 +24,7 @@ func TestMediaFile_Location(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = location.Find(conf.Db(), "places"); err != nil {
|
||||
if err = location.Find("places"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ func TestMediaFile_Location(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = location.Find(conf.Db(), "places"); err != nil {
|
||||
if err = location.Find("places"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ func TestMediaFile_Location(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = location.Find(conf.Db(), "places"); err != nil {
|
||||
if err = location.Find("places"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Example for using database fixtures defined in assets/resources/examples/fixtures.sql
|
||||
func TestCamera_FirstOrCreate(t *testing.T) {
|
||||
t.Run("iphone-se", func(t *testing.T) {
|
||||
camera := entity.NewCamera("iPhone SE", "Apple")
|
||||
c := config.TestConfig()
|
||||
camera.FirstOrCreate(c.Db())
|
||||
assert.GreaterOrEqual(t, camera.ID, uint(1))
|
||||
})
|
||||
}
|
|
@ -3,7 +3,6 @@ package query
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -26,8 +25,7 @@ func TestNewCountry(t *testing.T) {
|
|||
func TestCountry_FirstOrCreate(t *testing.T) {
|
||||
t.Run("country already existing", func(t *testing.T) {
|
||||
country := entity.NewCountry("de", "Germany")
|
||||
c := config.TestConfig()
|
||||
country.FirstOrCreate(c.Db())
|
||||
country.FirstOrCreate()
|
||||
assert.Equal(t, "de", country.Code())
|
||||
assert.Equal(t, "Germany", country.Name())
|
||||
assert.Equal(t, "Country Description", country.CountryDescription)
|
||||
|
@ -36,8 +34,7 @@ func TestCountry_FirstOrCreate(t *testing.T) {
|
|||
})
|
||||
t.Run("country not yet existing", func(t *testing.T) {
|
||||
country := entity.NewCountry("wl", "Wonder Land")
|
||||
c := config.TestConfig()
|
||||
country.FirstOrCreate(c.Db())
|
||||
country.FirstOrCreate()
|
||||
assert.Equal(t, "wl", country.Code())
|
||||
assert.Equal(t, "Wonder Land", country.Name())
|
||||
})
|
||||
|
|
|
@ -452,7 +452,7 @@ func (q *Query) PreloadPhotoByUUID(photoUUID string) (photo entity.Photo, err er
|
|||
return photo, err
|
||||
}
|
||||
|
||||
photo.PreloadMany(q.db)
|
||||
photo.PreloadMany()
|
||||
|
||||
return photo, nil
|
||||
}
|
||||
|
|
19
internal/service/query.go
Normal file
19
internal/service/query.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
)
|
||||
|
||||
var onceQuery sync.Once
|
||||
|
||||
func initQuery() {
|
||||
services.Query = query.New(Config().Db())
|
||||
}
|
||||
|
||||
func Query() *query.Query {
|
||||
onceQuery.Do(initQuery)
|
||||
|
||||
return services.Query
|
||||
}
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/nsfw"
|
||||
"github.com/photoprism/photoprism/internal/photoprism"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/internal/session"
|
||||
)
|
||||
|
||||
|
@ -18,6 +19,7 @@ var services struct {
|
|||
Resample *photoprism.Resample
|
||||
Classify *classify.TensorFlow
|
||||
Session *session.Session
|
||||
Query *query.Query
|
||||
}
|
||||
|
||||
func SetConfig(c *config.Config) {
|
||||
|
|
|
@ -62,7 +62,7 @@ func (s *Sync) refresh(a entity.Account) (complete bool, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
f.FirstOrCreate(db)
|
||||
f.FirstOrCreate()
|
||||
|
||||
if f.Status == entity.FileSyncIgnore && mediaType == fs.MediaRaw && a.SyncRaw {
|
||||
f.Status = entity.FileSyncNew
|
||||
|
|
Loading…
Reference in a new issue