feat: graph validation and custom JSON-LD
- seo_schema (seoschema, E8) with the C17 server rules: invalid JSON with line and column, non-objects, 16 KB, depth 8, a literal <script and a type outside the kind's list refused; the value re-serialised - a custom node with a generated @id merges into it (schema.merged save notice), other nodes are appended to the graph - seo_primary_parent (seoparent) for article types; both values stored in the entry data on every locale row - the seo_graph widget action (E9 data), P1 primary_gone and the P2 schema type and breadcrumb trail rows - GET /_seo/api/v1/graph and MCP seo_get_graph; seo_set_url_seo and apply_batch accept primary_parent and schema The graph tool lands with the validation: the operations parity test binds the seo_graph widget action to its tool.
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"git.golem15.com/golem15/sm-seo-plugin/classes/schema"
|
||||
"git.golem15.com/golem15/sm-seo-plugin/models"
|
||||
"git.golem15.com/golem15/summercms/modules/pact"
|
||||
"gorm.io/gorm"
|
||||
@@ -126,6 +127,9 @@ func (s *Service) SetURLSEO(ctx context.Context, tx *gorm.DB, in URLSEOWrite) (U
|
||||
for _, column := range EntryColumns {
|
||||
known[column] = true
|
||||
}
|
||||
for _, column := range DataColumns {
|
||||
known[column] = true
|
||||
}
|
||||
for column, raw := range in.Values {
|
||||
v := strings.TrimSpace(raw)
|
||||
switch {
|
||||
@@ -148,6 +152,27 @@ func (s *Service) SetURLSEO(ctx context.Context, tx *gorm.DB, in URLSEOWrite) (U
|
||||
case column == "og_image" && !ValidImageURL(v):
|
||||
problems[column] = append(problems[column], models.Problem{Key: errImageURL})
|
||||
continue
|
||||
case (column == DataPrimaryParent || column == DataSchema) && owner.WrittenTo != WrittenToRecord:
|
||||
if v != "" {
|
||||
problems[column] = append(problems[column], models.Problem{Key: "golem15.seo::lang.api.record_only"})
|
||||
}
|
||||
continue
|
||||
case column == DataPrimaryParent && v != "":
|
||||
found := false
|
||||
for _, opt := range s.ParentOptions(ctx, typ.Key, owner.ID, "") {
|
||||
found = found || opt.Value == v
|
||||
}
|
||||
if !found {
|
||||
problems[column] = append(problems[column], models.Problem{Key: "golem15.seo::lang.api.value_invalid"})
|
||||
continue
|
||||
}
|
||||
case column == DataSchema:
|
||||
stored, _, err := schema.Normalize(typ.Content.Kind, pageVariant(tx, typ.Key, owner.ID), v)
|
||||
if err != nil {
|
||||
problems[column] = append(problems[column], SchemaProblem(typ.Content.Kind, err))
|
||||
continue
|
||||
}
|
||||
v = stored
|
||||
}
|
||||
values[column] = v
|
||||
}
|
||||
@@ -181,6 +206,9 @@ func (s *Service) SetURLSEO(ctx context.Context, tx *gorm.DB, in URLSEOWrite) (U
|
||||
for _, column := range EntryColumns {
|
||||
out[column] = EntryValue(e, column)
|
||||
}
|
||||
for _, column := range DataColumns {
|
||||
out[column] = EntryValue(e, column)
|
||||
}
|
||||
return URLSEOResult{Owner: owner, Values: out}, nil
|
||||
}
|
||||
rule := models.Rule{URL: owner.URL, Match: models.MatchExact}
|
||||
|
||||
Reference in New Issue
Block a user