mirror of
https://github.com/foomo/gocontentful.git
synced 2025-10-16 12:25:39 +00:00
feat: improved asset and generic entry API, docs
This commit is contained in:
parent
bb57ab35b2
commit
8938a65f43
@ -241,9 +241,10 @@ a "Version mismatch" error. This is needed even if you have just upserted the en
|
|||||||
(vo *CfPerson) UpdateEntry(cc *ContentfulClient) (err error)
|
(vo *CfPerson) UpdateEntry(cc *ContentfulClient) (err error)
|
||||||
```
|
```
|
||||||
|
|
||||||
Shortcut function that upserts and publishes the entry. Note that before calling this you will need to retrieve the
|
First upserts the entry and then it publishes it only if it was already published before upserting.
|
||||||
entry with one of the Manage\* functions above to acquire the Sys object that contains the version information. Otherwise
|
The rationale is to respect the publishing status of entries and prevent unexpected go-live of content.
|
||||||
the API call will fail with a "Version mismatch" error. Using this shortcut function avoids retrieving the entry twice.
|
Note that before calling this you will need to retrieve theentry with one of the Manage\* functions above to acquire the Sys object that contains the version information.
|
||||||
|
Otherwise the API call will fail with a "Version mismatch" error. Using this shortcut function avoids retrieving the entry twice.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
(vo *CfPerson) DeleteEntry(cc *ContentfulClient) (err error)
|
(vo *CfPerson) DeleteEntry(cc *ContentfulClient) (err error)
|
||||||
@ -313,6 +314,21 @@ Sets a generic entry's field value.
|
|||||||
|
|
||||||
Upserts the generic entry to the space it came from.
|
Upserts the generic entry to the space it came from.
|
||||||
|
|
||||||
|
```go
|
||||||
|
(genericEntry *GenericEntry) Update(ctx context.Context) (err error)
|
||||||
|
```
|
||||||
|
|
||||||
|
Upserts the generic entry and publishes it only if it was already published before upserting. Only available for
|
||||||
|
ClientModeCMA. Before calling this you should retrieve the entry to acquire the Sys version; otherwise the API may fail
|
||||||
|
with a "Version mismatch" error.
|
||||||
|
|
||||||
|
```go
|
||||||
|
(genericEntry *GenericEntry) GetPublishingStatus() string
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the publishing status of the entry as per the Contentful editor UI. The value is one of `StatusDraft`,
|
||||||
|
`StatusChanged`, or `StatusPublished`.
|
||||||
|
|
||||||
### Asset functions
|
### Asset functions
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@ -352,6 +368,27 @@ ToAssetReference(asset *contentful.Asset) (refSys ContentTypeSys)
|
|||||||
|
|
||||||
Converts the asset to a reference. You need to do this before you add the asset to a reference field of an entry.
|
Converts the asset to a reference. You need to do this before you add the asset to a reference field of an entry.
|
||||||
|
|
||||||
|
```go
|
||||||
|
(cc *ContentfulClient) UpsertAsset(ctx context.Context, asset *contentful.Asset) error
|
||||||
|
```
|
||||||
|
|
||||||
|
Upserts an asset into the space. Only available for ClientModeCMA. Normalizes file URLs by removing the `https:` prefix
|
||||||
|
for each locale file, and tolerates idempotency errors returned by the SDK.
|
||||||
|
|
||||||
|
```go
|
||||||
|
(cc *ContentfulClient) PublishAsset(ctx context.Context, asset *contentful.Asset) error
|
||||||
|
```
|
||||||
|
|
||||||
|
Publishes an asset. Only available for ClientModeCMA. The call is idempotent and tolerates "Not published" responses
|
||||||
|
from the SDK.
|
||||||
|
|
||||||
|
```go
|
||||||
|
(cc *ContentfulClient) UpdateAsset(ctx context.Context, asset *contentful.Asset) (err error)
|
||||||
|
```
|
||||||
|
|
||||||
|
First upserts the asset and then publishes it only if it was already published before upserting. This respects the
|
||||||
|
current publishing status and avoids unintended go-live of assets. Only available for ClientModeCMA.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
(cc *ContentfulClient) DeleteAsset(asset *contentful.Asset) error
|
(cc *ContentfulClient) DeleteAsset(asset *contentful.Asset) error
|
||||||
```
|
```
|
||||||
|
|||||||
@ -30,7 +30,7 @@ type spaceConf struct {
|
|||||||
func getLocales(ctx context.Context, CMA *contentful.Contentful, spaceID string) (locales []Locale, err error) {
|
func getLocales(ctx context.Context, CMA *contentful.Contentful, spaceID string) (locales []Locale, err error) {
|
||||||
col, err := CMA.Locales.List(ctx, spaceID).GetAll()
|
col, err := CMA.Locales.List(ctx, spaceID).GetAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Couldn't get locales")
|
log.Fatalf("Couldn't get locales: %v", err)
|
||||||
}
|
}
|
||||||
for _, item := range col.Items {
|
for _, item := range col.Items {
|
||||||
var locale Locale
|
var locale Locale
|
||||||
@ -49,7 +49,6 @@ func getLocales(ctx context.Context, CMA *contentful.Contentful, spaceID string)
|
|||||||
|
|
||||||
// GetContentTypes retrieves content type definition from Contentful
|
// GetContentTypes retrieves content type definition from Contentful
|
||||||
func getContentTypes(ctx context.Context, CMA *contentful.Contentful, spaceID string) (contentTypes []ContentType, err error) {
|
func getContentTypes(ctx context.Context, CMA *contentful.Contentful, spaceID string) (contentTypes []ContentType, err error) {
|
||||||
|
|
||||||
col := CMA.ContentTypes.List(ctx, spaceID)
|
col := CMA.ContentTypes.List(ctx, spaceID)
|
||||||
_, err = col.GetAll()
|
_, err = col.GetAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -148,7 +147,7 @@ func GenerateAPI(ctx context.Context, dir, packageName, spaceID, cmaKey, environ
|
|||||||
}
|
}
|
||||||
|
|
||||||
packageDir := filepath.Join(dir, packageName)
|
packageDir := filepath.Join(dir, packageName)
|
||||||
errMkdir := os.MkdirAll(packageDir, 0766)
|
errMkdir := os.MkdirAll(packageDir, 0o766)
|
||||||
if errMkdir != nil {
|
if errMkdir != nil {
|
||||||
return errors.Wrap(errMkdir, "could not create target folder")
|
return errors.Wrap(errMkdir, "could not create target folder")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -277,6 +277,78 @@ func (ref ContentfulReferencedEntry) ContentType() (contentType string) {
|
|||||||
return ref.Entry.Sys.ContentType.Sys.ID
|
return ref.Entry.Sys.ContentType.Sys.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cc *ContentfulClient) UpsertAsset(ctx context.Context, asset *contentful.Asset) error {
|
||||||
|
if cc == nil || cc.Client == nil {
|
||||||
|
return errors.New("UpsertAsset: No client available")
|
||||||
|
}
|
||||||
|
if cc.clientMode != ClientModeCMA {
|
||||||
|
return errors.New("UpsertAsset: Only available in ClientModeCMA")
|
||||||
|
}
|
||||||
|
if asset.Fields != nil && asset.Fields.File != nil {
|
||||||
|
for _, locale := range SpaceLocales {
|
||||||
|
if asset.Fields.File[string(locale)] != nil {
|
||||||
|
asset.Fields.File[string(locale)].URL = strings.ReplaceAll(asset.Fields.File[string(locale)].URL, "https:", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errUpsert := cc.Client.Assets.Upsert(ctx, cc.SpaceID, asset)
|
||||||
|
if errUpsert != nil && !strings.Contains(errUpsert.Error(), "Not upserted") {
|
||||||
|
return errUpsert
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ContentfulClient) PublishAsset(ctx context.Context, asset *contentful.Asset) error {
|
||||||
|
if cc == nil || cc.Client == nil {
|
||||||
|
return errors.New("PublishAsset: No client available")
|
||||||
|
}
|
||||||
|
if cc.clientMode != ClientModeCMA {
|
||||||
|
return errors.New("PublishAsset: Only available in ClientModeCMA")
|
||||||
|
}
|
||||||
|
errPublish := cc.Client.Assets.Publish(ctx, cc.SpaceID, asset)
|
||||||
|
if errPublish != nil && !strings.Contains(errPublish.Error(), "Not published") {
|
||||||
|
return errPublish
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAssetPublishingStatus(asset *contentful.Asset) string {
|
||||||
|
if asset == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if asset.Sys.PublishedVersion == 0 {
|
||||||
|
return StatusDraft
|
||||||
|
}
|
||||||
|
if asset.Sys.Version-asset.Sys.PublishedVersion == 1 {
|
||||||
|
return StatusPublished
|
||||||
|
}
|
||||||
|
return StatusChanged
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ContentfulClient) UpdateAsset(ctx context.Context, asset *contentful.Asset) (err error) {
|
||||||
|
if asset == nil {
|
||||||
|
return errors.New("UpdateAsset: Generic Entry is nil")
|
||||||
|
}
|
||||||
|
if cc == nil {
|
||||||
|
return errors.New("UpdateAsset: Generic Entry has nil Contentful client")
|
||||||
|
}
|
||||||
|
if cc.clientMode != ClientModeCMA {
|
||||||
|
return errors.New("UpdateAsset: Generic Entry not in ClientModeCMA")
|
||||||
|
}
|
||||||
|
publishingStatus := GetAssetPublishingStatus(asset)
|
||||||
|
err = cc.UpsertAsset(ctx,asset)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("UpdateAsset: upsert operation failed: %w", err)
|
||||||
|
}
|
||||||
|
if publishingStatus == StatusPublished {
|
||||||
|
err = cc.PublishAsset(ctx, asset)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("UpdateAsset: publish operation failed: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (cc *ContentfulClient) DeleteAsset(ctx context.Context, asset *contentful.Asset) error {
|
func (cc *ContentfulClient) DeleteAsset(ctx context.Context, asset *contentful.Asset) error {
|
||||||
if cc == nil || cc.Client == nil {
|
if cc == nil || cc.Client == nil {
|
||||||
return errors.New("DeleteAsset: No client available")
|
return errors.New("DeleteAsset: No client available")
|
||||||
@ -919,6 +991,9 @@ func (genericEntry *GenericEntry) FieldAsReference(fieldName string, locale ...L
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if cts.Sys.ID == "" {
|
||||||
|
return nil, errors.New("not a reference")
|
||||||
|
}
|
||||||
referencedEntry, err := genericEntry.CC.GetGenericEntry(cts.Sys.ID)
|
referencedEntry, err := genericEntry.CC.GetGenericEntry(cts.Sys.ID)
|
||||||
if err != nil || referencedEntry == nil {
|
if err != nil || referencedEntry == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1049,6 +1124,9 @@ func (genericEntry *GenericEntry) FieldAsMultipleReference(fieldName string, loc
|
|||||||
}
|
}
|
||||||
var refs []*EntryReference
|
var refs []*EntryReference
|
||||||
for _, cts := range ctss {
|
for _, cts := range ctss {
|
||||||
|
if cts.Sys.ID == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
referencedEntry, err := genericEntry.CC.GetGenericEntry(cts.Sys.ID)
|
referencedEntry, err := genericEntry.CC.GetGenericEntry(cts.Sys.ID)
|
||||||
if err != nil || referencedEntry == nil {
|
if err != nil || referencedEntry == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1255,6 +1333,62 @@ func (genericEntry *GenericEntry) Upsert(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (genericEntry *GenericEntry) Update(ctx context.Context) (err error) {
|
||||||
|
if genericEntry == nil {
|
||||||
|
return errors.New("Update: Generic Entry is nil")
|
||||||
|
}
|
||||||
|
if genericEntry.CC == nil {
|
||||||
|
return errors.New("Update: Generic Entry has nil Contentful client")
|
||||||
|
}
|
||||||
|
if genericEntry.CC.clientMode != ClientModeCMA {
|
||||||
|
return errors.New("Update: Generic Entry not in ClientModeCMA")
|
||||||
|
}
|
||||||
|
publishingStatus := genericEntry.GetPublishingStatus()
|
||||||
|
cfEntry := &contentful.Entry{}
|
||||||
|
tmp, errMarshal := json.Marshal(genericEntry)
|
||||||
|
if errMarshal != nil {
|
||||||
|
return errors.New("Update: Can't marshal JSON from VO")
|
||||||
|
}
|
||||||
|
errUnmarshal := json.Unmarshal(tmp, &cfEntry)
|
||||||
|
if errUnmarshal != nil {
|
||||||
|
return errors.New("Update: Can't unmarshal JSON into CF entry")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = genericEntry.CC.Client.Entries.Upsert(ctx, genericEntry.CC.SpaceID, cfEntry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Update: upsert operation failed: %w", err)
|
||||||
|
}
|
||||||
|
tmp, errMarshal = json.Marshal(cfEntry)
|
||||||
|
if errMarshal != nil {
|
||||||
|
return errors.New("Update: Can't marshal JSON back from CF entry")
|
||||||
|
}
|
||||||
|
errUnmarshal = json.Unmarshal(tmp, &genericEntry)
|
||||||
|
if errUnmarshal != nil {
|
||||||
|
return errors.New("Update: Can't unmarshal JSON back into Generic Entry")
|
||||||
|
}
|
||||||
|
if publishingStatus == StatusPublished {
|
||||||
|
genericEntry.Sys.Version++
|
||||||
|
err = genericEntry.CC.Client.Entries.Publish(ctx, genericEntry.CC.SpaceID, cfEntry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Update: publish operation failed: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (genericEntry *GenericEntry) GetPublishingStatus() string {
|
||||||
|
if genericEntry == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if genericEntry.Sys.PublishedVersion == 0 {
|
||||||
|
return StatusDraft
|
||||||
|
}
|
||||||
|
if genericEntry.Sys.Version-genericEntry.Sys.PublishedVersion == 1 {
|
||||||
|
return StatusPublished
|
||||||
|
}
|
||||||
|
return StatusChanged
|
||||||
|
}
|
||||||
|
|
||||||
func (cc *ContentfulClient) ClientMode() ClientMode {
|
func (cc *ContentfulClient) ClientMode() ClientMode {
|
||||||
return cc.clientMode
|
return cc.clientMode
|
||||||
}
|
}
|
||||||
@ -2260,6 +2394,41 @@ func (n *RichTextGenericNode) richTextRenderHTML(w io.Writer, linkResolver LinkR
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements custom JSON marshalling for RichTextGenericNode for compatibility with Contentful's upsert API
|
||||||
|
func (n *RichTextGenericNode) MarshalJSON() ([]byte, error) {
|
||||||
|
if n == nil {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
if n.Data == nil {
|
||||||
|
n.Data = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
if n.NodeType == "text" {
|
||||||
|
// For text nodes, include Data, Value and Marks, but not Content
|
||||||
|
return json.Marshal(&struct {
|
||||||
|
NodeType string `json:"nodeType"`
|
||||||
|
Data map[string]interface{} `json:"data"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
Marks []RichTextMark `json:"marks"`
|
||||||
|
}{
|
||||||
|
NodeType: n.NodeType,
|
||||||
|
Data: n.Data,
|
||||||
|
Value: n.Value,
|
||||||
|
Marks: n.Marks,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// For non-text nodes, exclude Data and Marks
|
||||||
|
return json.Marshal(&struct {
|
||||||
|
NodeType string `json:"nodeType"`
|
||||||
|
Data map[string]interface{} `json:"data"`
|
||||||
|
Content []*RichTextGenericNode `json:"content"`
|
||||||
|
}{
|
||||||
|
NodeType: n.NodeType,
|
||||||
|
Content: n.Content,
|
||||||
|
Data: n.Data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func stringSliceContains(s []string, e string) bool {
|
func stringSliceContains(s []string, e string) bool {
|
||||||
for _, a := range s {
|
for _, a := range s {
|
||||||
if a == e {
|
if a == e {
|
||||||
|
|||||||
@ -625,6 +625,7 @@ func (vo *Cf{{ firstCap $contentType.Sys.ID }}) UpdateEntry(ctx context.Context)
|
|||||||
if vo.CC.clientMode != ClientModeCMA {
|
if vo.CC.clientMode != ClientModeCMA {
|
||||||
return errors.New("UpdateEntry: Only available in ClientModeCMA")
|
return errors.New("UpdateEntry: Only available in ClientModeCMA")
|
||||||
}
|
}
|
||||||
|
publishingStatus := vo.GetPublishingStatus()
|
||||||
cfEntry := &contentful.Entry{}
|
cfEntry := &contentful.Entry{}
|
||||||
tmp, errMarshal := json.Marshal(vo)
|
tmp, errMarshal := json.Marshal(vo)
|
||||||
if errMarshal != nil {
|
if errMarshal != nil {
|
||||||
@ -647,9 +648,12 @@ func (vo *Cf{{ firstCap $contentType.Sys.ID }}) UpdateEntry(ctx context.Context)
|
|||||||
if errUnmarshal != nil {
|
if errUnmarshal != nil {
|
||||||
return errors.New("Cf{{ firstCap $contentType.Sys.ID }} UpdateEntry: Can't unmarshal JSON back into VO")
|
return errors.New("Cf{{ firstCap $contentType.Sys.ID }} UpdateEntry: Can't unmarshal JSON back into VO")
|
||||||
}
|
}
|
||||||
err = vo.CC.Client.Entries.Publish(ctx, vo.CC.SpaceID, cfEntry)
|
if publishingStatus == StatusPublished {
|
||||||
if err != nil {
|
vo.Sys.Version++
|
||||||
return fmt.Errorf("Cf{{ firstCap $contentType.Sys.ID }} UpdateEntry: publish operation failed: %w", err)
|
err = vo.CC.Client.Entries.Publish(ctx, vo.CC.SpaceID, cfEntry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CfShopCategory UpdateEntry: publish operation failed: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -294,6 +294,78 @@ func (ref ContentfulReferencedEntry) ContentType() (contentType string) {
|
|||||||
return ref.Entry.Sys.ContentType.Sys.ID
|
return ref.Entry.Sys.ContentType.Sys.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cc *ContentfulClient) UpsertAsset(ctx context.Context, asset *contentful.Asset) error {
|
||||||
|
if cc == nil || cc.Client == nil {
|
||||||
|
return errors.New("UpsertAsset: No client available")
|
||||||
|
}
|
||||||
|
if cc.clientMode != ClientModeCMA {
|
||||||
|
return errors.New("UpsertAsset: Only available in ClientModeCMA")
|
||||||
|
}
|
||||||
|
if asset.Fields != nil && asset.Fields.File != nil {
|
||||||
|
for _, locale := range SpaceLocales {
|
||||||
|
if asset.Fields.File[string(locale)] != nil {
|
||||||
|
asset.Fields.File[string(locale)].URL = strings.ReplaceAll(asset.Fields.File[string(locale)].URL, "https:", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errUpsert := cc.Client.Assets.Upsert(ctx, cc.SpaceID, asset)
|
||||||
|
if errUpsert != nil && !strings.Contains(errUpsert.Error(), "Not upserted") {
|
||||||
|
return errUpsert
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ContentfulClient) PublishAsset(ctx context.Context, asset *contentful.Asset) error {
|
||||||
|
if cc == nil || cc.Client == nil {
|
||||||
|
return errors.New("PublishAsset: No client available")
|
||||||
|
}
|
||||||
|
if cc.clientMode != ClientModeCMA {
|
||||||
|
return errors.New("PublishAsset: Only available in ClientModeCMA")
|
||||||
|
}
|
||||||
|
errPublish := cc.Client.Assets.Publish(ctx, cc.SpaceID, asset)
|
||||||
|
if errPublish != nil && !strings.Contains(errPublish.Error(), "Not published") {
|
||||||
|
return errPublish
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAssetPublishingStatus(asset *contentful.Asset) string {
|
||||||
|
if asset == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if asset.Sys.PublishedVersion == 0 {
|
||||||
|
return StatusDraft
|
||||||
|
}
|
||||||
|
if asset.Sys.Version-asset.Sys.PublishedVersion == 1 {
|
||||||
|
return StatusPublished
|
||||||
|
}
|
||||||
|
return StatusChanged
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ContentfulClient) UpdateAsset(ctx context.Context, asset *contentful.Asset) (err error) {
|
||||||
|
if asset == nil {
|
||||||
|
return errors.New("UpdateAsset: Generic Entry is nil")
|
||||||
|
}
|
||||||
|
if cc == nil {
|
||||||
|
return errors.New("UpdateAsset: Generic Entry has nil Contentful client")
|
||||||
|
}
|
||||||
|
if cc.clientMode != ClientModeCMA {
|
||||||
|
return errors.New("UpdateAsset: Generic Entry not in ClientModeCMA")
|
||||||
|
}
|
||||||
|
publishingStatus := GetAssetPublishingStatus(asset)
|
||||||
|
err = cc.UpsertAsset(ctx, asset)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("UpdateAsset: upsert operation failed: %w", err)
|
||||||
|
}
|
||||||
|
if publishingStatus == StatusPublished {
|
||||||
|
err = cc.PublishAsset(ctx, asset)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("UpdateAsset: publish operation failed: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (cc *ContentfulClient) DeleteAsset(ctx context.Context, asset *contentful.Asset) error {
|
func (cc *ContentfulClient) DeleteAsset(ctx context.Context, asset *contentful.Asset) error {
|
||||||
if cc == nil || cc.Client == nil {
|
if cc == nil || cc.Client == nil {
|
||||||
return errors.New("DeleteAsset: No client available")
|
return errors.New("DeleteAsset: No client available")
|
||||||
@ -949,6 +1021,9 @@ func (genericEntry *GenericEntry) FieldAsReference(fieldName string, locale ...L
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if cts.Sys.ID == "" {
|
||||||
|
return nil, errors.New("not a reference")
|
||||||
|
}
|
||||||
referencedEntry, err := genericEntry.CC.GetGenericEntry(cts.Sys.ID)
|
referencedEntry, err := genericEntry.CC.GetGenericEntry(cts.Sys.ID)
|
||||||
if err != nil || referencedEntry == nil {
|
if err != nil || referencedEntry == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1079,6 +1154,9 @@ func (genericEntry *GenericEntry) FieldAsMultipleReference(fieldName string, loc
|
|||||||
}
|
}
|
||||||
var refs []*EntryReference
|
var refs []*EntryReference
|
||||||
for _, cts := range ctss {
|
for _, cts := range ctss {
|
||||||
|
if cts.Sys.ID == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
referencedEntry, err := genericEntry.CC.GetGenericEntry(cts.Sys.ID)
|
referencedEntry, err := genericEntry.CC.GetGenericEntry(cts.Sys.ID)
|
||||||
if err != nil || referencedEntry == nil {
|
if err != nil || referencedEntry == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1284,6 +1362,62 @@ func (genericEntry *GenericEntry) Upsert(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (genericEntry *GenericEntry) Update(ctx context.Context) (err error) {
|
||||||
|
if genericEntry == nil {
|
||||||
|
return errors.New("Update: Generic Entry is nil")
|
||||||
|
}
|
||||||
|
if genericEntry.CC == nil {
|
||||||
|
return errors.New("Update: Generic Entry has nil Contentful client")
|
||||||
|
}
|
||||||
|
if genericEntry.CC.clientMode != ClientModeCMA {
|
||||||
|
return errors.New("Update: Generic Entry not in ClientModeCMA")
|
||||||
|
}
|
||||||
|
publishingStatus := genericEntry.GetPublishingStatus()
|
||||||
|
cfEntry := &contentful.Entry{}
|
||||||
|
tmp, errMarshal := json.Marshal(genericEntry)
|
||||||
|
if errMarshal != nil {
|
||||||
|
return errors.New("Update: Can't marshal JSON from VO")
|
||||||
|
}
|
||||||
|
errUnmarshal := json.Unmarshal(tmp, &cfEntry)
|
||||||
|
if errUnmarshal != nil {
|
||||||
|
return errors.New("Update: Can't unmarshal JSON into CF entry")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = genericEntry.CC.Client.Entries.Upsert(ctx, genericEntry.CC.SpaceID, cfEntry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Update: upsert operation failed: %w", err)
|
||||||
|
}
|
||||||
|
tmp, errMarshal = json.Marshal(cfEntry)
|
||||||
|
if errMarshal != nil {
|
||||||
|
return errors.New("Update: Can't marshal JSON back from CF entry")
|
||||||
|
}
|
||||||
|
errUnmarshal = json.Unmarshal(tmp, &genericEntry)
|
||||||
|
if errUnmarshal != nil {
|
||||||
|
return errors.New("Update: Can't unmarshal JSON back into Generic Entry")
|
||||||
|
}
|
||||||
|
if publishingStatus == StatusPublished {
|
||||||
|
genericEntry.Sys.Version++
|
||||||
|
err = genericEntry.CC.Client.Entries.Publish(ctx, genericEntry.CC.SpaceID, cfEntry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Update: publish operation failed: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (genericEntry *GenericEntry) GetPublishingStatus() string {
|
||||||
|
if genericEntry == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if genericEntry.Sys.PublishedVersion == 0 {
|
||||||
|
return StatusDraft
|
||||||
|
}
|
||||||
|
if genericEntry.Sys.Version-genericEntry.Sys.PublishedVersion == 1 {
|
||||||
|
return StatusPublished
|
||||||
|
}
|
||||||
|
return StatusChanged
|
||||||
|
}
|
||||||
|
|
||||||
func (cc *ContentfulClient) ClientMode() ClientMode {
|
func (cc *ContentfulClient) ClientMode() ClientMode {
|
||||||
return cc.clientMode
|
return cc.clientMode
|
||||||
}
|
}
|
||||||
@ -2303,6 +2437,41 @@ func (n *RichTextGenericNode) richTextRenderHTML(w io.Writer, linkResolver LinkR
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements custom JSON marshalling for RichTextGenericNode for compatibility with Contentful's upsert API
|
||||||
|
func (n *RichTextGenericNode) MarshalJSON() ([]byte, error) {
|
||||||
|
if n == nil {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
if n.Data == nil {
|
||||||
|
n.Data = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
if n.NodeType == "text" {
|
||||||
|
// For text nodes, include Data, Value and Marks, but not Content
|
||||||
|
return json.Marshal(&struct {
|
||||||
|
NodeType string `json:"nodeType"`
|
||||||
|
Data map[string]interface{} `json:"data"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
Marks []RichTextMark `json:"marks"`
|
||||||
|
}{
|
||||||
|
NodeType: n.NodeType,
|
||||||
|
Data: n.Data,
|
||||||
|
Value: n.Value,
|
||||||
|
Marks: n.Marks,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// For non-text nodes, exclude Data and Marks
|
||||||
|
return json.Marshal(&struct {
|
||||||
|
NodeType string `json:"nodeType"`
|
||||||
|
Data map[string]interface{} `json:"data"`
|
||||||
|
Content []*RichTextGenericNode `json:"content"`
|
||||||
|
}{
|
||||||
|
NodeType: n.NodeType,
|
||||||
|
Content: n.Content,
|
||||||
|
Data: n.Data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func stringSliceContains(s []string, e string) bool {
|
func stringSliceContains(s []string, e string) bool {
|
||||||
for _, a := range s {
|
for _, a := range s {
|
||||||
if a == e {
|
if a == e {
|
||||||
|
|||||||
@ -712,6 +712,7 @@ func (vo *CfBrand) UpdateEntry(ctx context.Context) (err error) {
|
|||||||
if vo.CC.clientMode != ClientModeCMA {
|
if vo.CC.clientMode != ClientModeCMA {
|
||||||
return errors.New("UpdateEntry: Only available in ClientModeCMA")
|
return errors.New("UpdateEntry: Only available in ClientModeCMA")
|
||||||
}
|
}
|
||||||
|
publishingStatus := vo.GetPublishingStatus()
|
||||||
cfEntry := &contentful.Entry{}
|
cfEntry := &contentful.Entry{}
|
||||||
tmp, errMarshal := json.Marshal(vo)
|
tmp, errMarshal := json.Marshal(vo)
|
||||||
if errMarshal != nil {
|
if errMarshal != nil {
|
||||||
@ -734,9 +735,12 @@ func (vo *CfBrand) UpdateEntry(ctx context.Context) (err error) {
|
|||||||
if errUnmarshal != nil {
|
if errUnmarshal != nil {
|
||||||
return errors.New("CfBrand UpdateEntry: Can't unmarshal JSON back into VO")
|
return errors.New("CfBrand UpdateEntry: Can't unmarshal JSON back into VO")
|
||||||
}
|
}
|
||||||
err = vo.CC.Client.Entries.Publish(ctx, vo.CC.SpaceID, cfEntry)
|
if publishingStatus == StatusPublished {
|
||||||
if err != nil {
|
vo.Sys.Version++
|
||||||
return fmt.Errorf("CfBrand UpdateEntry: publish operation failed: %w", err)
|
err = vo.CC.Client.Entries.Publish(ctx, vo.CC.SpaceID, cfEntry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CfShopCategory UpdateEntry: publish operation failed: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -476,6 +476,7 @@ func (vo *CfCategory) UpdateEntry(ctx context.Context) (err error) {
|
|||||||
if vo.CC.clientMode != ClientModeCMA {
|
if vo.CC.clientMode != ClientModeCMA {
|
||||||
return errors.New("UpdateEntry: Only available in ClientModeCMA")
|
return errors.New("UpdateEntry: Only available in ClientModeCMA")
|
||||||
}
|
}
|
||||||
|
publishingStatus := vo.GetPublishingStatus()
|
||||||
cfEntry := &contentful.Entry{}
|
cfEntry := &contentful.Entry{}
|
||||||
tmp, errMarshal := json.Marshal(vo)
|
tmp, errMarshal := json.Marshal(vo)
|
||||||
if errMarshal != nil {
|
if errMarshal != nil {
|
||||||
@ -498,9 +499,12 @@ func (vo *CfCategory) UpdateEntry(ctx context.Context) (err error) {
|
|||||||
if errUnmarshal != nil {
|
if errUnmarshal != nil {
|
||||||
return errors.New("CfCategory UpdateEntry: Can't unmarshal JSON back into VO")
|
return errors.New("CfCategory UpdateEntry: Can't unmarshal JSON back into VO")
|
||||||
}
|
}
|
||||||
err = vo.CC.Client.Entries.Publish(ctx, vo.CC.SpaceID, cfEntry)
|
if publishingStatus == StatusPublished {
|
||||||
if err != nil {
|
vo.Sys.Version++
|
||||||
return fmt.Errorf("CfCategory UpdateEntry: publish operation failed: %w", err)
|
err = vo.CC.Client.Entries.Publish(ctx, vo.CC.SpaceID, cfEntry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CfShopCategory UpdateEntry: publish operation failed: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1314,6 +1314,7 @@ func (vo *CfProduct) UpdateEntry(ctx context.Context) (err error) {
|
|||||||
if vo.CC.clientMode != ClientModeCMA {
|
if vo.CC.clientMode != ClientModeCMA {
|
||||||
return errors.New("UpdateEntry: Only available in ClientModeCMA")
|
return errors.New("UpdateEntry: Only available in ClientModeCMA")
|
||||||
}
|
}
|
||||||
|
publishingStatus := vo.GetPublishingStatus()
|
||||||
cfEntry := &contentful.Entry{}
|
cfEntry := &contentful.Entry{}
|
||||||
tmp, errMarshal := json.Marshal(vo)
|
tmp, errMarshal := json.Marshal(vo)
|
||||||
if errMarshal != nil {
|
if errMarshal != nil {
|
||||||
@ -1336,9 +1337,12 @@ func (vo *CfProduct) UpdateEntry(ctx context.Context) (err error) {
|
|||||||
if errUnmarshal != nil {
|
if errUnmarshal != nil {
|
||||||
return errors.New("CfProduct UpdateEntry: Can't unmarshal JSON back into VO")
|
return errors.New("CfProduct UpdateEntry: Can't unmarshal JSON back into VO")
|
||||||
}
|
}
|
||||||
err = vo.CC.Client.Entries.Publish(ctx, vo.CC.SpaceID, cfEntry)
|
if publishingStatus == StatusPublished {
|
||||||
if err != nil {
|
vo.Sys.Version++
|
||||||
return fmt.Errorf("CfProduct UpdateEntry: publish operation failed: %w", err)
|
err = vo.CC.Client.Entries.Publish(ctx, vo.CC.SpaceID, cfEntry)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CfShopCategory UpdateEntry: publish operation failed: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
// gocontentful version: 1.1.1
|
// gocontentful version: 1.1.2
|
||||||
package testapi
|
package testapi
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user