feat(12.2-03): add hasMany relation contracts, relation forms and child create
- RelationContract gains Kind (empty is belongsToMany) and ForeignKey, with kind-aware boot checks
- manage.form, view.form and pivot.form compile against the related or pivot model; $/ paths resolve inside the plugin
- view toolbarButtons accept create|update|delete|link|unlink, each the capability of its routes
- POST .../relations/{name}/records creates a child through the manage form; the server sets the hasMany key
- relation schema carries kind, deferrable and the localized forms; 17 new relation message keys in en and pl
This commit is contained in:
@@ -34,10 +34,22 @@ func readAsset(fsys fs.FS, name string) ([]byte, error) {
|
||||
return fs.ReadFile(fsys, name)
|
||||
}
|
||||
|
||||
// assetPath resolves a YAML file reference to a path inside the plugin's
|
||||
// AdminFS: a plugin-relative path, ~/plugins/<vendor>/<plugin>/rest, or
|
||||
// WinterCMS's $/<vendor>/<plugin>/rest ($/ is the plugins directory). A $/
|
||||
// path into another plugin cannot be read from this plugin's tree and is an
|
||||
// error.
|
||||
func assetPath(pluginID, ref string) (string, error) {
|
||||
ref = strings.TrimSpace(ref)
|
||||
own := strings.ReplaceAll(pluginID, ".", "/") + "/"
|
||||
if rest, ok := strings.CutPrefix(ref, "$/"); ok {
|
||||
if !strings.HasPrefix(rest, own) {
|
||||
return "", fmt.Errorf("$/ path %s names another plugin", ref)
|
||||
}
|
||||
ref = strings.TrimPrefix(rest, own)
|
||||
}
|
||||
ref = strings.TrimPrefix(ref, "~/")
|
||||
prefix := "plugins/" + strings.ReplaceAll(pluginID, ".", "/") + "/"
|
||||
prefix := "plugins/" + own
|
||||
ref = strings.TrimPrefix(ref, prefix)
|
||||
ref = path.Clean(ref)
|
||||
if ref == "." || strings.HasPrefix(ref, "..") || strings.Contains(ref, "..") {
|
||||
|
||||
Reference in New Issue
Block a user