Exemplo n.º 1
0
        public virtual ActionResult PropertyItemHtml(object data, string propertyPath, int depth, string pathPrefix)
        {
            ViewData["propertyPath"] = (pathPrefix ?? "") + propertyPath;
            ViewData["addDepth"]     = depth - 1;
            string parentPath   = propertyPath.Contains(".") ? propertyPath.UpToLast(".") : "";
            string propertyName = (propertyPath.Contains(".") ? propertyPath.LastAfter(".") : propertyPath).UpTo("[");
            Type   parentType   = ReflectionX.GetPropertyTypeByPath(data.GetType(), parentPath);
            IList  list         = ReflectionX.GetPropertyValueByPath(data, propertyPath, true) as IList;
            var    listProp     = ReflectionX.GetPropertyByPath(data.GetType(), propertyPath);
            Type   listType     = listProp.PropertyType;

            if (listType.GetType().IsArray)
            {
                list    = (IList)Array.CreateInstance(ReflectionX.ElementType(listType), 1);
                list[0] = CreateInstance(listType.GetElementType());
            }
            else
            {
                list = (IList)Activator.CreateInstance(listType);
                list.Add(CreateInstance(ReflectionX.ElementType(listType)));
            }

            ViewData["list"] = list;
            var metadata = new DataAnnotationsModelMetadataProvider().GetMetadataForProperty(null, parentType, propertyName);

            ViewData["CollectionAdditionalValues"] = metadata.AdditionalValues;

            RouteData.DataTokens.Add("CancelProcessingHtml", true);
            return(PartialView(ConfigHelper.GetViewPath("LyniconPropertyItem.cshtml"), data));
        }
Exemplo n.º 2
0
        protected void DoEditAction(object data, string editAction)
        {
            IList list;
            Type  itemType;

            switch (editAction.UpTo("-"))
            {
            case "add":
                list     = ReflectionX.GetPropertyValueByPath(data, editAction.After("-")) as IList;
                itemType = list.GetType().GetGenericArguments()[0];
                if (list != null)
                {
                    list.Add(CreateInstance(itemType));
                }
                break;

            case "del":
                list     = ReflectionX.GetPropertyValueByPath(data, editAction.After("-").UpToLast("[")) as IList;
                itemType = list.GetType().GetGenericArguments()[0];
                if (list != null)
                {
                    ModelState.Clear();     // templating system will take old values out of the ModelState unless you do this
                    list.RemoveAt(int.Parse(editAction.LastAfter("[").UpTo("]")));
                }
                break;
            }
        }
Exemplo n.º 3
0
        public IActionResult Rename(string dataType, string path, bool pathInSummary, string newPath, bool newPathInSummary, bool?isDelete)
        {
            Type contentType = ContentTypeHierarchy.GetContentType(dataType);

            if (contentType == null)
            {
                return(Content("No such type, remember to add 'Content' where necessary"));
            }
            int propMissing = 0;
            int updated     = 0;

            // create a new ContentRepository so we can bypass any block to writing caused by existing data problems
            // on the global data api
            var repo = new ContentRepository(new CoreDataSourceFactory(LyniconSystem.Instance));

            repo.BypassChangeProblems = true;

            foreach (ContentItem ci in repo.Get <ContentItem>(contentType, new Type[] { contentType }, iq => iq))
            {
                JObject jObjFrom;
                if (pathInSummary)
                {
                    jObjFrom = JObject.Parse(ci.Summary ?? "{}");
                }
                else
                {
                    jObjFrom = JObject.Parse(ci.Content ?? "{}");
                }

                JObject jObjTo      = null;
                bool    doDelete    = isDelete ?? false;
                bool    wasComputed = false;
                if (!doDelete)
                {
                    if (newPathInSummary)
                    {
                        jObjTo = JObject.Parse(ci.Summary ?? "{}");
                    }
                    else
                    {
                        jObjTo = JObject.Parse(ci.Content ?? "{}");
                    }

                    jObjTo.CopyPropertyFrom(newPath, jObjFrom, path);
                    JProperty prop = jObjTo.PropertyByPath(path);

                    // try to deserialize in case its a computed property
                    if (!pathInSummary && newPathInSummary && prop == null)
                    {
                        object content = jObjFrom.ToObject(contentType);
                        object val     = ReflectionX.GetPropertyValueByPath(content, path);
                        if (val != null)
                        {
                            string pName = newPath.Contains(".") ? newPath.LastAfter(".") : newPath;
                            jObjTo.AddAtPath(newPath, new JProperty(pName, val));
                            wasComputed = true;
                        }
                    }

                    if (pathInSummary == newPathInSummary)
                    {
                        if (prop != null)
                        {
                            prop.Remove();
                            updated++;
                        }
                        else
                        {
                            propMissing++;
                        }
                    }
                }

                if (pathInSummary != newPathInSummary || doDelete) // we need to update both summary and content
                {
                    // remove the old path
                    JProperty prop = jObjFrom.PropertyByPath(path);
                    if (prop != null)
                    {
                        prop.Remove();
                        updated++;

                        if (pathInSummary)
                        {
                            ci.Summary = jObjFrom.ToString();
                        }
                        else
                        {
                            ci.Content = jObjFrom.ToString();
                        }
                    }
                    else if (wasComputed)
                    {
                        updated++;
                    }
                    else
                    {
                        propMissing++;
                    }
                }

                if (!doDelete)
                {
                    if (newPathInSummary)
                    {
                        ci.Summary = jObjTo.ToString();
                    }
                    else
                    {
                        ci.Content = jObjTo.ToString();
                    }
                }

                repo.Set(new List <object> {
                    ci
                }, new Dictionary <string, object>());
            }

            return(Content(string.Format("{0} updated {1} had property missing", updated, propMissing)));
        }
Exemplo n.º 4
0
        public static void SetReferenceProperties(object o, List <ReferenceProperty> refProps)
        {
            object curr           = o;
            string currLeafParent = "";

            foreach (var refProp in refProps)
            {
                string       path         = refProp.PropertyPath;
                string       leafParent   = path.Contains(".") ? path.UpToLast(".") : "";
                string       leafProperty = path.Contains(".") ? path.LastAfter(".") : path;
                PropertyInfo pi           = null;

                if (currLeafParent != leafParent)
                {
                    curr = ReflectionX.GetPropertyValueByPath(o, leafParent);
                }

                if (curr != null)
                {
                    pi = curr.GetType().GetProperty(leafProperty.UpTo("["));
                }

                if (pi == null)
                {
                    log.Debug("Tried to assign reference value to property " + path + " on " + o.GetType().FullName);
                    continue;
                }

                if (typeof(Reference).IsAssignableFrom(pi.PropertyType))
                {
                    if (pi.PropertyType.IsGenericType)
                    {
                        pi.SetValue(curr, refProp.ToReference(pi.PropertyType.GetGenericArguments()[0]));
                    }
                    else
                    {
                        pi.SetValue(curr, refProp.ToReference());
                    }
                }
                else
                {
                    bool   found    = false;
                    string indexStr = leafProperty.After("[").UpTo("]");
                    int    idx      = -1;
                    int.TryParse(indexStr, out idx);

                    // Now look for the property to be an IList of References
                    if (idx > -1)
                    {
                        foreach (Type interf in pi.PropertyType.GetInterfaces())
                        {
                            if (interf.GetGenericTypeDefinition() == typeof(IList <>))
                            {
                                found = true;
                                Type elType = interf.GetGenericArguments()[0];
                                if (!typeof(Reference).IsAssignableFrom(elType))
                                {
                                    throw new Exception("Cannot insert references into list at " + path + " of element type " + elType.FullName);
                                }
                                Reference refForList = null;
                                if (elType.IsGenericType)
                                {
                                    refForList = refProp.ToReference(elType.GetGenericArguments()[0]);
                                }
                                else
                                {
                                    refForList = refProp.ToReference();
                                }

                                object refList = pi.GetValue(curr);
                                if (refList == null)
                                {
                                    refList = Activator.CreateInstance(pi.PropertyType);
                                    pi.SetValue(curr, refList);
                                }
                                int count = (int)refList.GetType().GetProperty("Count").GetValue(refList);
                                if (count < idx)
                                {
                                    throw new Exception("Reference index " + idx + " at path " + path + " longer than maximum " + (count - 1));
                                }
                                if (count == idx)
                                {
                                    refList.GetType().GetMethod("Add").Invoke(refList, new object[] { refForList });
                                }
                                else
                                {
                                    refList.GetType().GetProperty("Item").SetValue(refList, refForList, new object[] { idx });
                                }

                                break;
                            }
                        }
                    }

                    if (!found)
                    {
                        throw new Exception("Trying to SetReferenceProperties on a non reference property " + path);
                    }
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Starting from a list of addresses and optionally (or only) the containers at those addresses, fetch
        /// any containers necessary and any other containers required to supply redirected properties for them,
        /// obtain the contained content items and collate their properties, returning the content items at the
        /// addresses.
        /// </summary>
        /// <typeparam name="T">Type of content items to return</typeparam>
        /// <param name="startContainers">Initial list of containers if they are available</param>
        /// <param name="startAddresses">Initial list of addresses, which may be omitted and derived from containers</param>
        /// <returns>List of content items</returns>
        public IEnumerable <T> Collate <T>(IEnumerable <object> startContainers, IEnumerable <Address> startAddresses) where T : class
        {
            // place to store all the containers we have currently
            Dictionary <VersionedAddress, object> containers;
            ItemVersion containerCommonVersion;

            startAddresses = startAddresses ?? Enumerable.Empty <Address>();

            (containers, containerCommonVersion) = ProcessContainers(startContainers);

            List <Address> fetchAddrs = startAddresses
                                        .Where(sa => !containers.Any(kvp => kvp.Key.Address == sa)).ToList();

            List <IGrouping <Type, Address> > allStartAddressesByType = null;

            if (DoCollation)
            {
                allStartAddressesByType = fetchAddrs.Concat(containers.Keys)
                                          .GroupBy(a => a.Type)
                                          .ToList();

                // Get all addresses for items to collate (startAddresses plus addresses from startContainers)
                foreach (var addrTypeG in allStartAddressesByType)
                {
                    Type contentType   = addrTypeG.Key;
                    var  rpsAttributes = contentType
                                         .GetCustomAttributes(typeof(RedirectPropertySourceAttribute), true)
                                         .Cast <RedirectPropertySourceAttribute>()
                                         .ToList();
                    foreach (Address addr in addrTypeG)
                    {
                        fetchAddrs.AddRange(rpsAttributes
                                            .Select(attr => new Address(attr.ContentType ?? contentType,
                                                                        PathFunctions.Redirect(addr.GetAsContentPath(), attr.SourceDescriptor))));
                    }
                }
                fetchAddrs = fetchAddrs.Distinct().ToList();
            }

            bool pushVersion = (startContainers != null && DoCollation);

            if (pushVersion) // Get containers in any version that might be relevant to a start container
            {
                System.Versions.PushState(VersioningMode.Specific, containerCommonVersion);
            }

            try
            {
                // Get all the containers for collation (if current version is not fully specified, may be multiple per address)
                foreach (var cont in System.Repository.Get(typeof(object), fetchAddrs))
                {
                    var va = new VersionedAddress(System, cont);
                    if (containers.ContainsKey(va))
                    {
                        log.Error("Duplicate versioned address in db: " + va.ToString());
                    }
                    else
                    {
                        containers.Add(new VersionedAddress(new Address(cont), new ItemVersion(System, cont).Canonicalise()), cont);
                    }
                }
            }
            finally
            {
                if (pushVersion)
                {
                    System.Versions.PopState();
                }
            }

            if (!DoCollation)
            {
                // just return the containers we have
                foreach (object cont in containers.Values)
                {
                    yield return(cont as T);
                }
                yield break;
            }

            // Create a lookup by (non-versioned) address of all the containers we have
            var contLookup = containers.ToLookup(kvp => kvp.Key.Address.ToString(), kvp => kvp.Value);

            // We have the data, now collate it into the content from the startContainers
            foreach (var addrTypeG in allStartAddressesByType)
            {
                // Process all the start addresses (including those of the start containers) of a given type

                Type contentType   = addrTypeG.Key;
                var  rpsAttributes = contentType
                                     .GetCustomAttributes(typeof(RedirectPropertySourceAttribute), true)
                                     .Cast <RedirectPropertySourceAttribute>()
                                     .ToList();

                foreach (var addr in addrTypeG.Select(a => new Address(a.Type, a)).Distinct()) // convert a VersionedAddress to an Address if necessary
                {
                    var primaryPath = addr.GetAsContentPath();
                    if (!contLookup.Contains(new Address(addr.Type, addr).ToString()))
                    {
                        continue;
                    }

                    foreach (var cont in contLookup[addr.ToString()])
                    {
                        object primaryContent = cont;

                        if (primaryContent is IContentContainer)
                        {
                            primaryContent = ((IContentContainer)primaryContent).GetContent(System.Extender);
                        }

                        foreach (var rpsAttribute in rpsAttributes)
                        {
                            var refAddress = new VersionedAddress(
                                rpsAttribute.ContentType ?? contentType,
                                PathFunctions.Redirect(primaryPath, rpsAttribute.SourceDescriptor),
                                new ItemVersion(System, cont).Canonicalise()
                                );
                            if (refAddress.Address == addr) // redirected to itself, ignore
                            {
                                continue;
                            }
                            object refItem = containers.ContainsKey(refAddress) ? containers[refAddress] : null;
                            if (refItem is IContentContainer)
                            {
                                refItem = ((IContentContainer)refItem).GetContent(System.Extender);
                            }
                            if (refItem != null)
                            {
                                foreach (string propertyPath in rpsAttribute.PropertyPaths)
                                {
                                    var    toFromPaths = GetPaths(propertyPath);
                                    object val         = ReflectionX.GetPropertyValueByPath(refItem, toFromPaths[1]);
                                    var    piSet       = ReflectionX.GetPropertyByPath(primaryContent.GetType(), toFromPaths[0]);
                                    piSet.SetValue(primaryContent, val);
                                }
                            }
                        }

                        yield return(primaryContent as T);
                    }
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Starting from a list of addresses and optionally (or only) the containers at those addresses, fetch
        /// any containers necessary and any other containers required to supply redirected properties for them,
        /// obtain the contained content items and collate their properties, returning the content items at the
        /// addresses.
        /// </summary>
        /// <typeparam name="T">Type of content items to return</typeparam>
        /// <param name="startContainers">Initial list of containers if they are available</param>
        /// <param name="startAddresses">Initial list of addresses, which may be omitted and derived from containers</param>
        /// <returns>List of content items</returns>
        public IEnumerable <T> Collate <T>(IEnumerable <object> startContainers, IEnumerable <Address> startAddresses) where T : class
        {
            // place to store all the containers we have currently
            var containers = new Dictionary <VersionedAddress, object>();

            ItemVersion containerCommonVersion = null;

            // Ensure we have the start addresses
            if (startContainers != null)
            {
                containers             = startContainers.ToDictionary(sc => new VersionedAddress(sc), sc => sc);
                startAddresses         = containers.Keys.Select(va => va.Address).Distinct().ToList();
                containerCommonVersion = ItemVersion.LeastAbstractCommonVersion(containers.Keys.Select(va => va.Version));
            }

            var fetchAddrs = startAddresses
                             .GroupBy(a => a.Type.GetCustomAttributes <RedirectPropertySourceAttribute>())
                             .SelectMany(ag =>
                                         ag.SelectMany(a => ag.Key
                                                       .Select(attr => attr.Redirect(a))
                                                       .Concat(a)))
                             .Distinct()
                             .Except(containers.Keys.Select(va => va.Address))
                             .ToList();

            bool pushVersion = (startContainers != null);

            if (pushVersion) // Get containers in any version that might be relevant to a start container
            {
                VersionManager.Instance.PushState(VersioningMode.Specific, containerCommonVersion);
            }

            try
            {
                // Get all the containers for collation (if current version is not fully specified, may be multiple per address)
                foreach (var cont in Repository.Instance.Get(typeof(object), fetchAddrs))
                {
                    var va = new VersionedAddress(cont);
                    if (containers.ContainsKey(va))
                    {
                        log.Error("Duplicate versioned address in db: " + va.ToString());
                    }
                    else
                    {
                        containers.Add(new VersionedAddress(cont), cont);
                    }
                }
            }
            finally
            {
                if (pushVersion)
                {
                    VersionManager.Instance.PopState();
                }
            }

            var contLookup = containers.ToLookup(kvp => kvp.Key.Address.ToString(), kvp => kvp.Value);

            if (startContainers == null)
            {
                startContainers = startAddresses.SelectMany(a => contLookup[a.ToString()]);
            }

            // We have the data, now collate it into the content from the startContainers
            foreach (var addrTypeG in startAddresses.GroupBy(a => a.Type))
            {
                // Process all the start addresses of a given type

                Type contentType   = addrTypeG.Key;
                var  rpsAttributes = contentType
                                     .GetCustomAttributes(typeof(RedirectPropertySourceAttribute), false)
                                     .Cast <RedirectPropertySourceAttribute>()
                                     .ToList();

                foreach (var addr in addrTypeG)
                {
                    var primaryPath = addr.GetAsContentPath();
                    if (!contLookup.Contains(addr.ToString()))
                    {
                        continue;
                    }

                    foreach (var cont in contLookup[addr.ToString()])
                    {
                        object primaryContent = cont;

                        if (primaryContent is IContentContainer)
                        {
                            primaryContent = ((IContentContainer)primaryContent).GetContent();
                        }

                        foreach (var rpsAttribute in rpsAttributes)
                        {
                            var refAddress = new VersionedAddress(
                                rpsAttribute.ContentType ?? contentType,
                                PathFunctions.Redirect(primaryPath, rpsAttribute.SourceDescriptor),
                                new ItemVersion(cont)
                                );
                            if (refAddress.Address == addr) // redirected to itself, ignore
                            {
                                continue;
                            }
                            object refItem = containers.ContainsKey(refAddress) ? containers[refAddress] : null;
                            if (refItem is IContentContainer)
                            {
                                refItem = ((IContentContainer)refItem).GetContent();
                            }
                            if (refItem != null)
                            {
                                foreach (string propertyPath in rpsAttribute.PropertyPaths)
                                {
                                    var    toFromPaths = GetPaths(propertyPath);
                                    object val         = ReflectionX.GetPropertyValueByPath(refItem, toFromPaths[1]);
                                    var    piSet       = ReflectionX.GetPropertyByPath(primaryContent.GetType(), toFromPaths[0]);
                                    piSet.SetValue(primaryContent, val);
                                }
                            }
                        }

                        yield return(primaryContent as T);
                    }
                }
            }
        }