예제 #1
0
func savePage(c context.Context, pageKey *datastore.Key, p *model.Page, props map[string]string) error {

	err := datastore.RunInTransaction(c, func(c context.Context) error {
		var p2 model.Page
		if !pageKey.Incomplete() {
			if err := ds.Get(c, pageKey, &p2); err != nil {
				if errors.Root(err) != datastore.ErrNoSuchEntity {
					return errors.WrapOr(err)
				} else {
					p2 = model.Page{}
					p2.Key = pageKey
				}
			}
		}

		oldAlias := p2.Alias

		p2.Name = p.Name
		p2.Alias = p.Alias
		p2.Leaf = p.Leaf

		aliasChanged := oldAlias != p2.Alias

		if err := ds.Put(c, &p2); err != nil {
			return errors.WrapOr(err)
		}

		if aliasChanged && p2.Alias != "" {
			newAliasKey := model.NewPageAliasKey(c, p2.Alias)

			var pa model.PageAlias
			if err := ds.Get(c, newAliasKey, &pa); err == nil {
				return ErrPageAliasAlreadyExists
			} else {
				newAlias := model.PageAlias{}
				newAlias.Key = newAliasKey
				newAlias.PageKey = pageKey

				if err := ds.Put(c, &newAlias); err != nil {
					return errors.WrapOr(err)
				}
			}
		}

		if aliasChanged && oldAlias != "" {
			oldAliasKey := model.NewPageAliasKey(c, oldAlias)

			err := ds.Delete(c, oldAliasKey)
			if err != nil {
				return err
			}
		}

		// TODO: put multi
		for name, value := range props {
			initial, _ := utf8.DecodeRune([]byte(name))
			global := unicode.IsUpper(initial)

			var pkey *datastore.Key
			if global {
				pkey = model.NewGlobalPageKey(c)
			} else {
				pkey = pageKey
			}
			propKey := model.NewPagePropertyKey(c, name, pkey)

			var prop model.PageProperty
			err := ds.Get(c, propKey, &prop)
			if err == nil {
				prop.Key = propKey
				prop.Value = value
			}

			if err != nil {
				if errors.Root(err) != datastore.ErrNoSuchEntity {
					return errors.WrapOr(err)
				} else {
					prop = model.PageProperty{}
					prop.Key = propKey
					prop.Value = value
				}
			}

			if err = ds.Put(c, &prop); err != nil {
				return errors.WrapOr(err)
			}
		}

		return nil
	}, &datastore.TransactionOptions{XG: true})

	if err != nil {
		return err
	}
	return nil
}