Esempio n. 1
0
        protected override void ExecuteCmdlet()
        {
            if (!System.IO.Path.IsPathRooted(Path))
            {
                Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
            }

            var template = ReadSiteTemplate
                           .LoadSiteTemplateFromFile(Path,
                                                     TemplateProviderExtensions, (e) =>
            {
                WriteError(new ErrorRecord(e, "TEMPLATENOTVALID", ErrorCategory.SyntaxError, null));
            });

            if (template == null)
            {
                throw new ApplicationException("Invalid template file!");
            }
            //We will remove a list if it's found so we can get the list

            ListInstance listInstance = template.Lists.Find(l => l.Title == List.Title);

            if (listInstance == null)
            {
                throw new ApplicationException("List does not exist in the template file!");
            }

            List spList = List.GetList(SelectedWeb);

            ClientContext.Load(spList, l => l.RootFolder, l => l.HasUniqueRoleAssignments);
            ClientContext.ExecuteQueryRetry();

            if (TokenizeUrls.IsPresent)
            {
                ClientContext.Load(ClientContext.Web, w => w.Url, w => w.ServerRelativeUrl, w => w.Id);
                ClientContext.Load(ClientContext.Site, s => s.Url, s => s.ServerRelativeUrl, s => s.Id);
                ClientContext.Load(ClientContext.Web.Lists, lists => lists.Include(l => l.Title, l => l.RootFolder.ServerRelativeUrl));
            }

            CamlQuery query = new CamlQuery();

            var viewFieldsStringBuilder = new StringBuilder();

            if (Fields != null)
            {
                viewFieldsStringBuilder.Append("<ViewFields>");
                foreach (var field in Fields)
                {
                    viewFieldsStringBuilder.AppendFormat("<FieldRef Name='{0}'/>", field);
                }
                viewFieldsStringBuilder.Append("</ViewFields>");
            }

            query.ViewXml = string.Format("<View>{0}{1}</View>", Query, viewFieldsStringBuilder);
            var listItems = spList.GetItems(query);

            ClientContext.Load(listItems, lI => lI.Include(l => l.HasUniqueRoleAssignments, l => l.ContentType.StringId));
            ClientContext.ExecuteQueryRetry();

            Microsoft.SharePoint.Client.FieldCollection fieldCollection = spList.Fields;
            ClientContext.Load(fieldCollection, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind, f => f.ReadOnlyField));
            ClientContext.ExecuteQueryRetry();

            var rows = new DataRowCollection(template);

            foreach (var listItem in listItems)
            {
                //Make sure we don't pull Folders.. Of course this won't work
                if (listItem.ServerObjectIsNull == false)
                {
                    ClientContext.Load(listItem);
                    ClientContext.ExecuteQueryRetry();
                    if (!(listItem.FileSystemObjectType == FileSystemObjectType.Folder))
                    {
                        DataRow row = new DataRow();
                        if (IncludeSecurity && listItem.HasUniqueRoleAssignments)
                        {
                            row.Security.ClearSubscopes      = true;
                            row.Security.CopyRoleAssignments = false;

                            var roleAssignments = listItem.RoleAssignments;
                            ClientContext.Load(roleAssignments);
                            ClientContext.ExecuteQueryRetry();

                            ClientContext.Load(roleAssignments, r => r.Include(a => a.Member.LoginName, a => a.Member, a => a.RoleDefinitionBindings));
                            ClientContext.ExecuteQueryRetry();

                            foreach (var roleAssignment in roleAssignments)
                            {
                                var principalName = roleAssignment.Member.LoginName;
                                var roleBindings  = roleAssignment.RoleDefinitionBindings;
                                foreach (var roleBinding in roleBindings)
                                {
                                    row.Security.RoleAssignments.Add(new PnP.Framework.Provisioning.Model.RoleAssignment()
                                    {
                                        Principal = principalName, RoleDefinition = roleBinding.Name
                                    });
                                }
                            }
                        }
                        if (Fields != null)
                        {
                            foreach (var fieldName in Fields)
                            {
                                Microsoft.SharePoint.Client.Field dataField = fieldCollection.FirstOrDefault(f => f.InternalName == fieldName);

                                if (dataField != null)
                                {
                                    var defaultFieldValue = GetFieldValueAsText(ClientContext.Web, listItem, dataField);
                                    if (TokenizeUrls.IsPresent)
                                    {
                                        defaultFieldValue = Tokenize(defaultFieldValue, ClientContext.Web, ClientContext.Site);
                                    }

                                    row.Values.Add(fieldName, defaultFieldValue);
                                }
                            }
                        }
                        else
                        {
                            //All fields are added except readonly fields and unsupported field type
                            var fieldsToExport = fieldCollection.AsEnumerable()
                                                 .Where(f => !f.ReadOnlyField && !_unsupportedFieldTypes.Contains(f.FieldTypeKind));
                            foreach (var field in fieldsToExport)
                            {
                                var fldKey = (from f in listItem.FieldValues.Keys where f == field.InternalName select f).FirstOrDefault();
                                if (!string.IsNullOrEmpty(fldKey))
                                {
                                    var fieldValue = GetFieldValueAsText(ClientContext.Web, listItem, field);
                                    if (TokenizeUrls.IsPresent)
                                    {
                                        fieldValue = Tokenize(fieldValue, ClientContext.Web, ClientContext.Site);
                                    }
                                    row.Values.Add(field.InternalName, fieldValue);
                                }
                            }
                        }

                        rows.Add(row);
                    }
                }
            }
            template.Lists.Remove(listInstance);
            listInstance.DataRows.AddRange(rows);
            template.Lists.Add(listInstance);

            var outFileName = System.IO.Path.GetFileName(Path);
            var outPath     = new FileInfo(Path).DirectoryName;

            var fileSystemConnector = new FileSystemConnector(outPath, "");
            var formatter           = XMLPnPSchemaFormatter.LatestFormatter;
            var extension           = new FileInfo(Path).Extension.ToLowerInvariant();

            if (extension == ".pnp")
            {
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(Path, fileSystemConnector));
                var templateFileName         = outFileName.Substring(0, outFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                provider.SaveAs(template, templateFileName, formatter, TemplateProviderExtensions);
            }
            else
            {
                XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(Path, "");
                provider.SaveAs(template, Path, formatter, TemplateProviderExtensions);
            }
        }
Esempio n. 2
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (!template.Lists.Any())
                {
                    return(parser);
                }

                web.EnsureProperties(w => w.ServerRelativeUrl);

                web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                web.Context.ExecuteQueryRetry();

                #region DataRows

                foreach (var listInstance in template.Lists)
                {
                    if (listInstance.DataRows != null && listInstance.DataRows.Any())
                    {
                        scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                        // Retrieve the target list
                        var list = web.Lists.GetByTitle(parser.ParseString(listInstance.Title));
                        web.Context.Load(list);

                        // Retrieve the fields' types from the list
                        Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                        web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind, f => f.TypeAsString, f => f.ReadOnlyField, f => f.Title));
                        web.Context.ExecuteQueryRetry();

                        var keyColumnType   = "Text";
                        var parsedKeyColumn = parser.ParseString(listInstance.DataRows.KeyColumn);
                        if (!string.IsNullOrEmpty(parsedKeyColumn))
                        {
                            var keyColumn = fields.FirstOrDefault(f => f.InternalName.Equals(parsedKeyColumn, StringComparison.InvariantCultureIgnoreCase));
                            if (keyColumn != null)
                            {
                                switch (keyColumn.FieldTypeKind)
                                {
                                case FieldType.User:
                                case FieldType.Lookup:
                                    keyColumnType = "Lookup";
                                    break;

                                case FieldType.URL:
                                    keyColumnType = "Url";
                                    break;

                                case FieldType.DateTime:
                                    keyColumnType = "DateTime";
                                    break;

                                case FieldType.Number:
                                case FieldType.Counter:
                                    keyColumnType = "Number";
                                    break;
                                }
                            }
                        }

                        foreach (var dataRow in listInstance.DataRows)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);

                                bool     processItem = true;
                                ListItem listitem    = null;

                                if (!string.IsNullOrEmpty(listInstance.DataRows.KeyColumn))
                                {
                                    // Get value from key column
                                    var dataRowValues = dataRow.Values.Where(v => v.Key == listInstance.DataRows.KeyColumn).ToList();

                                    // if it is empty, skip the check
                                    if (dataRowValues.Any())
                                    {
                                        var query     = $@"<View><Query><Where><Eq><FieldRef Name=""{parsedKeyColumn}""/><Value Type=""{keyColumnType}"">{parser.ParseString(dataRowValues.FirstOrDefault().Value)}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>";
                                        var camlQuery = new CamlQuery()
                                        {
                                            ViewXml = query
                                        };
                                        var existingItems = list.GetItems(camlQuery);
                                        list.Context.Load(existingItems);
                                        list.Context.ExecuteQueryRetry();
                                        if (existingItems.Count > 0)
                                        {
                                            if (listInstance.DataRows.UpdateBehavior == UpdateBehavior.Skip)
                                            {
                                                processItem = false;
                                            }
                                            else
                                            {
                                                listitem    = existingItems[0];
                                                processItem = true;
                                            }
                                        }
                                    }
                                }

                                if (processItem)
                                {
                                    if (listitem == null)
                                    {
                                        var listitemCI = new ListItemCreationInformation();
                                        listitem = list.AddItem(listitemCI);
                                    }

                                    ListItemUtilities.UpdateListItem(listitem, parser, dataRow.Values, ListItemUtilities.ListItemUpdateType.UpdateOverwriteVersion);

                                    if (dataRow.Security != null && (dataRow.Security.ClearSubscopes || dataRow.Security.CopyRoleAssignments || dataRow.Security.RoleAssignments.Count > 0))
                                    {
                                        listitem.SetSecurity(parser, dataRow.Security);
                                    }
                                }
                            }
                            catch (ServerException ex)
                            {
                                if (ex.ServerErrorTypeName.Equals("Microsoft.SharePoint.SPDuplicateValuesFoundException", StringComparison.InvariantCultureIgnoreCase) &&
                                    applyingInformation.IgnoreDuplicateDataRowErrors)
                                {
                                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_duplicate);
                                    continue;
                                }
                            }
                            catch (Exception ex)
                            {
                                scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                    }
                }

                #endregion DataRows
            }

            return(parser);
        }
Esempio n. 3
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Lists.Any())
                {
                    var rootWeb = (web.Context as ClientContext).Site.RootWeb;

                    web.EnsureProperties(w => w.ServerRelativeUrl);

                    web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                    web.Context.ExecuteQueryRetry();
                    var existingLists     = web.Lists.AsEnumerable <List>().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    #region DataRows

                    foreach (var listInstance in template.Lists)
                    {
                        if (listInstance.DataRows != null && listInstance.DataRows.Any())
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                            // Retrieve the target list
                            var list = web.Lists.GetByTitle(listInstance.Title);
                            web.Context.Load(list);

                            // Retrieve the fields' types from the list
                            Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                            web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind));
                            web.Context.ExecuteQueryRetry();

                            foreach (var dataRow in listInstance.DataRows)
                            {
                                try
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);
                                    var listitemCI = new ListItemCreationInformation();
                                    var listitem   = list.AddItem(listitemCI);

                                    foreach (var dataValue in dataRow.Values)
                                    {
                                        Field dataField = fields.FirstOrDefault(
                                            f => f.InternalName == parser.ParseString(dataValue.Key));

                                        if (dataField != null)
                                        {
                                            String fieldValue = parser.ParseString(dataValue.Value);

                                            switch (dataField.FieldTypeKind)
                                            {
                                            case FieldType.Geolocation:
                                                // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                                var geolocationArray = fieldValue.Split(',');
                                                if (geolocationArray.Length == 4)
                                                {
                                                    var geolocationValue = new FieldGeolocationValue
                                                    {
                                                        Altitude  = Double.Parse(geolocationArray[0]),
                                                        Latitude  = Double.Parse(geolocationArray[1]),
                                                        Longitude = Double.Parse(geolocationArray[2]),
                                                        Measure   = Double.Parse(geolocationArray[3]),
                                                    };
                                                    listitem[parser.ParseString(dataValue.Key)] = geolocationValue;
                                                }
                                                else
                                                {
                                                    listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                }
                                                break;

                                            case FieldType.Lookup:
                                                // FieldLookupValue - Expected format: LookupID or LookupID,LookupID,LookupID...
                                                if (fieldValue.Contains(","))
                                                {
                                                    var lookupValues = new List <FieldLookupValue>();
                                                    fieldValue.Split(',').All(value =>
                                                    {
                                                        lookupValues.Add(new FieldLookupValue
                                                        {
                                                            LookupId = int.Parse(value),
                                                        });
                                                        return(true);
                                                    });
                                                    listitem[parser.ParseString(dataValue.Key)] = lookupValues.ToArray();
                                                }
                                                else
                                                {
                                                    var lookupValue = new FieldLookupValue
                                                    {
                                                        LookupId = int.Parse(fieldValue),
                                                    };
                                                    listitem[parser.ParseString(dataValue.Key)] = lookupValue;
                                                }
                                                break;

                                            case FieldType.URL:
                                                // FieldUrlValue - Expected format: URL,Description
                                                var urlArray  = fieldValue.Split(',');
                                                var linkValue = new FieldUrlValue();
                                                if (urlArray.Length == 2)
                                                {
                                                    linkValue.Url         = urlArray[0];
                                                    linkValue.Description = urlArray[1];
                                                }
                                                else
                                                {
                                                    linkValue.Url         = urlArray[0];
                                                    linkValue.Description = urlArray[0];
                                                }
                                                listitem[parser.ParseString(dataValue.Key)] = linkValue;
                                                break;

                                            case FieldType.User:
                                                // FieldUserValue - Expected format: loginName or loginName,loginName,loginName...
                                                if (fieldValue.Contains(","))
                                                {
                                                    var userValues = new List <FieldUserValue>();
                                                    fieldValue.Split(',').All(value =>
                                                    {
                                                        var user = web.EnsureUser(value);
                                                        web.Context.Load(user);
                                                        web.Context.ExecuteQueryRetry();
                                                        if (user != null)
                                                        {
                                                            userValues.Add(new FieldUserValue
                                                            {
                                                                LookupId = user.Id,
                                                            });;
                                                        }
                                                        return(true);
                                                    });
                                                    listitem[parser.ParseString(dataValue.Key)] = userValues.ToArray();
                                                }
                                                else
                                                {
                                                    var user = web.EnsureUser(fieldValue);
                                                    web.Context.Load(user);
                                                    web.Context.ExecuteQueryRetry();
                                                    if (user != null)
                                                    {
                                                        var userValue = new FieldUserValue
                                                        {
                                                            LookupId = user.Id,
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = userValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                }
                                                break;

                                            case FieldType.DateTime:
                                                var dateTime = DateTime.MinValue;
                                                if (DateTime.TryParse(fieldValue, out dateTime))
                                                {
                                                    listitem[parser.ParseString(dataValue.Key)] = dateTime;
                                                }
                                                break;

                                            default:
                                                listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                break;
                                            }
                                        }
                                        listitem.Update();
                                    }
                                    web.Context.ExecuteQueryRetry();                                     // TODO: Run in batches?

                                    if (dataRow.Security != null && dataRow.Security.RoleAssignments.Count != 0)
                                    {
                                        listitem.SetSecurity(parser, dataRow.Security);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                    throw;
                                }
                            }
                        }
                    }

                    #endregion
                }
            }

            return(parser);
        }
Esempio n. 4
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Lists.Any())
                {
                    var rootWeb = (web.Context as ClientContext).Site.RootWeb;

                    web.EnsureProperties(w => w.ServerRelativeUrl);

                    web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                    web.Context.ExecuteQueryRetry();
                    var existingLists     = web.Lists.AsEnumerable <List>().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    #region DataRows

                    foreach (var listInstance in template.Lists)
                    {
                        if (listInstance.DataRows != null && listInstance.DataRows.Any())
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                            // Retrieve the target list
                            var list = web.Lists.GetByTitle(parser.ParseString(listInstance.Title));
                            web.Context.Load(list);

                            // Retrieve the fields' types from the list
                            Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                            web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind, f => f.TypeAsString));
                            web.Context.ExecuteQueryRetry();

                            var keyColumnType   = "Text";
                            var parsedKeyColumn = parser.ParseString(listInstance.DataRows.KeyColumn);
                            if (!string.IsNullOrEmpty(parsedKeyColumn))
                            {
                                var keyColumn = fields.FirstOrDefault(f => f.InternalName.Equals(parsedKeyColumn, StringComparison.InvariantCultureIgnoreCase));
                                if (keyColumn != null)
                                {
                                    switch (keyColumn.FieldTypeKind)
                                    {
                                    case FieldType.User:
                                    case FieldType.Lookup:
                                        keyColumnType = "Lookup";
                                        break;

                                    case FieldType.URL:
                                        keyColumnType = "Url";
                                        break;

                                    case FieldType.DateTime:
                                        keyColumnType = "DateTime";
                                        break;

                                    case FieldType.Number:
                                    case FieldType.Counter:
                                        keyColumnType = "Number";
                                        break;
                                    }
                                }
                            }

                            foreach (var dataRow in listInstance.DataRows)
                            {
                                try
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);


                                    bool     create   = true;
                                    ListItem listitem = null;
                                    if (!string.IsNullOrEmpty(listInstance.DataRows.KeyColumn))
                                    {
                                        // Get value from key column
                                        var dataRowValues = dataRow.Values.Where(v => v.Key == listInstance.DataRows.KeyColumn);

                                        // if it is empty, skip the check
                                        if (dataRowValues.Any())
                                        {
                                            var query     = $@"<View><Query><Where><Eq><FieldRef Name=""{parsedKeyColumn}""/><Value Type=""{keyColumnType}"">{dataRowValues.FirstOrDefault().Value}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>";
                                            var camlQuery = new CamlQuery()
                                            {
                                                ViewXml = query
                                            };
                                            var existingItems = list.GetItems(camlQuery);
                                            list.Context.Load(existingItems);
                                            list.Context.ExecuteQueryRetry();
                                            if (existingItems.Count > 0)
                                            {
                                                if (listInstance.DataRows.UpdateBehavior == UpdateBehavior.Skip)
                                                {
                                                    create = false;
                                                }
                                                else
                                                {
                                                    listitem = existingItems[0];
                                                    create   = true;
                                                }
                                            }
                                        }
                                    }

                                    if (create)
                                    {
                                        if (listitem == null)
                                        {
                                            var listitemCI = new ListItemCreationInformation();
                                            listitem = list.AddItem(listitemCI);
                                        }

                                        foreach (var dataValue in dataRow.Values)
                                        {
                                            Field dataField = fields.FirstOrDefault(
                                                f => f.InternalName == parser.ParseString(dataValue.Key));

                                            if (dataField != null)
                                            {
                                                String fieldValue = parser.ParseString(dataValue.Value);

                                                switch (dataField.FieldTypeKind)
                                                {
                                                case FieldType.Geolocation:
                                                    // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                                    var geolocationArray = fieldValue.Split(',');
                                                    if (geolocationArray.Length == 4)
                                                    {
                                                        var geolocationValue = new FieldGeolocationValue
                                                        {
                                                            Altitude  = Double.Parse(geolocationArray[0]),
                                                            Latitude  = Double.Parse(geolocationArray[1]),
                                                            Longitude = Double.Parse(geolocationArray[2]),
                                                            Measure   = Double.Parse(geolocationArray[3]),
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = geolocationValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                    break;

                                                case FieldType.Lookup:
                                                    // FieldLookupValue - Expected format: LookupID or LookupID,LookupID,LookupID...
                                                    if (fieldValue.Contains(","))
                                                    {
                                                        var lookupValues = new List <FieldLookupValue>();
                                                        fieldValue.Split(',').All(value =>
                                                        {
                                                            lookupValues.Add(new FieldLookupValue
                                                            {
                                                                LookupId = int.Parse(value),
                                                            });
                                                            return(true);
                                                        });
                                                        listitem[parser.ParseString(dataValue.Key)] = lookupValues.ToArray();
                                                    }
                                                    else
                                                    {
                                                        var lookupValue = new FieldLookupValue
                                                        {
                                                            LookupId = int.Parse(fieldValue),
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = lookupValue;
                                                    }
                                                    break;

                                                case FieldType.URL:
                                                    // FieldUrlValue - Expected format: URL,Description
                                                    var urlArray  = fieldValue.Split(',');
                                                    var linkValue = new FieldUrlValue();
                                                    if (urlArray.Length == 2)
                                                    {
                                                        linkValue.Url         = urlArray[0];
                                                        linkValue.Description = urlArray[1];
                                                    }
                                                    else
                                                    {
                                                        linkValue.Url         = urlArray[0];
                                                        linkValue.Description = urlArray[0];
                                                    }
                                                    listitem[parser.ParseString(dataValue.Key)] = linkValue;
                                                    break;

                                                case FieldType.User:
                                                    // FieldUserValue - Expected format: loginName or loginName,loginName,loginName...
                                                    if (fieldValue.Contains(","))
                                                    {
                                                        var userValues = new List <FieldUserValue>();
                                                        fieldValue.Split(',').All(value =>
                                                        {
                                                            var user = web.EnsureUser(value);
                                                            web.Context.Load(user);
                                                            web.Context.ExecuteQueryRetry();
                                                            if (user != null)
                                                            {
                                                                userValues.Add(new FieldUserValue
                                                                {
                                                                    LookupId = user.Id,
                                                                });;
                                                            }
                                                            return(true);
                                                        });
                                                        listitem[parser.ParseString(dataValue.Key)] = userValues.ToArray();
                                                    }
                                                    else
                                                    {
                                                        var user = web.EnsureUser(fieldValue);
                                                        web.Context.Load(user);
                                                        web.Context.ExecuteQueryRetry();
                                                        if (user != null)
                                                        {
                                                            var userValue = new FieldUserValue
                                                            {
                                                                LookupId = user.Id,
                                                            };
                                                            listitem[parser.ParseString(dataValue.Key)] = userValue;
                                                        }
                                                        else
                                                        {
                                                            listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                        }
                                                    }
                                                    break;

                                                case FieldType.DateTime:
                                                    var dateTime = DateTime.MinValue;
                                                    if (DateTime.TryParse(fieldValue, out dateTime))
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = dateTime;
                                                    }
                                                    break;

                                                default:
                                                    listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    break;
                                                }
                                                listitem.Update();
                                            }
                                        }
                                        web.Context.ExecuteQueryRetry(); // TODO: Run in batches?

                                        if (dataRow.Security != null && (dataRow.Security.ClearSubscopes == true || dataRow.Security.CopyRoleAssignments == true || dataRow.Security.RoleAssignments.Count > 0))
                                        {
                                            listitem.SetSecurity(parser, dataRow.Security);
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    if (ex.GetType().Equals(typeof(ServerException)) &&
                                        (ex as ServerException).ServerErrorTypeName.Equals("Microsoft.SharePoint.SPDuplicateValuesFoundException", StringComparison.InvariantCultureIgnoreCase) &&
                                        applyingInformation.IgnoreDuplicateDataRowErrors)
                                    {
                                        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_duplicate);
                                        continue;
                                    }
                                    else
                                    {
                                        scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                        throw;
                                    }
                                }
                            }
                        }
                    }

                    #endregion
                }
            }

            return(parser);
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (!template.Lists.Any())
                {
                    return(parser);
                }

                web.EnsureProperties(w => w.ServerRelativeUrl);

                web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                web.Context.ExecuteQueryRetry();

                #region DataRows
                foreach (var listInstance in template.Lists)
                {
                    if (listInstance.DataRows == null || !listInstance.DataRows.Any())
                    {
                        continue;
                    }

                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                    // Retrieve the target list
                    var list = web.Lists.GetByTitle(parser.ParseString(listInstance.Title));
                    web.Context.Load(list);

                    // Retrieve the fields' types from the list
                    Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                    web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind, f => f.TypeAsString, f => f.ReadOnlyField, f => f.Title));
                    web.Context.ExecuteQueryRetry();

                    var keyColumnType   = "Text";
                    var parsedKeyColumn = parser.ParseString(listInstance.DataRows.KeyColumn);
                    if (!string.IsNullOrEmpty(parsedKeyColumn))
                    {
                        var keyColumn = fields.FirstOrDefault(f => f.InternalName.Equals(parsedKeyColumn, StringComparison.InvariantCultureIgnoreCase));
                        if (keyColumn != null)
                        {
                            switch (keyColumn.FieldTypeKind)
                            {
                            case FieldType.User:
                            case FieldType.Lookup:
                                keyColumnType = "Lookup";
                                break;

                            case FieldType.URL:
                                keyColumnType = "Url";
                                break;

                            case FieldType.DateTime:
                                keyColumnType = "DateTime";
                                break;

                            case FieldType.Number:
                            case FieldType.Counter:
                                keyColumnType = "Number";
                                break;
                            }
                        }
                    }

                    foreach (var dataRow in listInstance.DataRows)
                    {
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);


                            bool     processItem  = true;
                            ListItem listitem     = null;
                            var      updateValues = new List <FieldUpdateValue>();

                            if (!string.IsNullOrEmpty(listInstance.DataRows.KeyColumn))
                            {
                                // Get value from key column
                                var dataRowValues = dataRow.Values.Where(v => v.Key == listInstance.DataRows.KeyColumn).ToList();

                                // if it is empty, skip the check
                                if (dataRowValues.Any())
                                {
                                    var query     = $@"<View><Query><Where><Eq><FieldRef Name=""{parsedKeyColumn}""/><Value Type=""{keyColumnType}"">{parser.ParseString(dataRowValues.FirstOrDefault().Value)}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>";
                                    var camlQuery = new CamlQuery()
                                    {
                                        ViewXml = query
                                    };
                                    var existingItems = list.GetItems(camlQuery);
                                    list.Context.Load(existingItems);
                                    list.Context.ExecuteQueryRetry();
                                    if (existingItems.Count > 0)
                                    {
                                        if (listInstance.DataRows.UpdateBehavior == UpdateBehavior.Skip)
                                        {
                                            processItem = false;
                                        }
                                        else
                                        {
                                            listitem    = existingItems[0];
                                            processItem = true;
                                        }
                                    }
                                }
                            }

                            if (!processItem)
                            {
                                continue;
                            }

                            if (listitem == null)
                            {
                                var listitemCI = new ListItemCreationInformation();
                                listitem = list.AddItem(listitemCI);
                            }

                            foreach (var dataValue in dataRow.Values)
                            {
                                Field dataField = fields.FirstOrDefault(
                                    f => f.InternalName == parser.ParseString(dataValue.Key));

                                if (dataField != null && dataField.ReadOnlyField &&
                                    !dataField.InternalName.Equals("ContentTypeId", StringComparison.OrdinalIgnoreCase))
                                {
                                    // skip read only fields, except ContentTypeId
                                    continue;
                                }

                                if (dataField == null)
                                {
                                    continue;
                                }

                                if (dataValue.Value == null)
                                {
                                    updateValues.Add(dataField.FieldTypeKind == FieldType.Invalid
                                        ? new FieldUpdateValue(dataValue.Key, null, dataField.TypeAsString)
                                        : new FieldUpdateValue(dataValue.Key, null));
                                }
                                else
                                {
                                    String fieldValue = parser.ParseString(dataValue.Value);

                                    switch (dataField.FieldTypeKind)
                                    {
                                    case FieldType.Geolocation:
                                        // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                        var geolocationArray = fieldValue.Split(',');
                                        if (geolocationArray.Length == 4)
                                        {
                                            var geolocationValue = new FieldGeolocationValue
                                            {
                                                Altitude  = Double.Parse(geolocationArray[0]),
                                                Latitude  = Double.Parse(geolocationArray[1]),
                                                Longitude = Double.Parse(geolocationArray[2]),
                                                Measure   = Double.Parse(geolocationArray[3]),
                                            };
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, geolocationValue));
                                        }
                                        else
                                        {
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, fieldValue));
                                        }
                                        break;

                                    case FieldType.Lookup:
                                        // FieldLookupValue - Expected format: LookupID or LookupID,LookupID,LookupID...
                                        if (fieldValue.Contains(","))
                                        {
                                            var lookupValues = new List <FieldLookupValue>();
                                            fieldValue.Split(',').All(value =>
                                            {
                                                lookupValues.Add(new FieldLookupValue
                                                {
                                                    LookupId = int.Parse(value),
                                                });
                                                return(true);
                                            });
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, lookupValues.ToArray()));
                                        }
                                        else
                                        {
                                            var lookupValue = new FieldLookupValue
                                            {
                                                LookupId = int.Parse(fieldValue),
                                            };
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, lookupValue));
                                        }
                                        break;

                                    case FieldType.URL:
                                        // FieldUrlValue - Expected format: URL,Description
                                        var urlArray  = fieldValue.Split(',');
                                        var linkValue = new FieldUrlValue();
                                        if (urlArray.Length == 2)
                                        {
                                            linkValue.Url         = urlArray[0];
                                            linkValue.Description = urlArray[1];
                                        }
                                        else
                                        {
                                            linkValue.Url         = urlArray[0];
                                            linkValue.Description = urlArray[0];
                                        }
                                        updateValues.Add(new FieldUpdateValue(dataValue.Key, linkValue));
                                        break;

                                    case FieldType.User:
                                        // FieldUserValue - Expected format: loginName or loginName,loginName,loginName...
                                        if (fieldValue.Contains(","))
                                        {
                                            var userValues = new List <FieldUserValue>();
                                            fieldValue.Split(',').All(value =>
                                            {
                                                var user = web.EnsureUser(value);
                                                web.Context.Load(user);
                                                web.Context.ExecuteQueryRetry();
                                                if (user != null)
                                                {
                                                    userValues.Add(new FieldUserValue
                                                    {
                                                        LookupId = user.Id,
                                                    });;
                                                }
                                                return(true);
                                            });
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, userValues.ToArray()));
                                        }
                                        else
                                        {
                                            var user = web.EnsureUser(fieldValue);
                                            web.Context.Load(user);
                                            web.Context.ExecuteQueryRetry();
                                            if (user != null)
                                            {
                                                var userValue = new FieldUserValue
                                                {
                                                    LookupId = user.Id,
                                                };
                                                updateValues.Add(new FieldUpdateValue(dataValue.Key, userValue));
                                            }
                                            else
                                            {
                                                updateValues.Add(new FieldUpdateValue(dataValue.Key, fieldValue));
                                            }
                                        }
                                        break;

                                    case FieldType.DateTime:
                                        var dateTime = DateTime.MinValue;
                                        if (DateTime.TryParse(fieldValue, out dateTime))
                                        {
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, dateTime));
                                        }
                                        break;

                                    case FieldType.Invalid:
                                        switch (dataField.TypeAsString)
                                        {
                                        case "TaxonomyFieldType":
                                        // Single value field - Expected format: term label|term GUID
                                        case "TaxonomyFieldTypeMulti":
                                            // Multi value field - Expected format: term label|term GUID;term label|term GUID;term label|term GUID;...
                                        {
                                            if (fieldValue != null)
                                            {
                                                var termStrings = new List <string>();

                                                var termsArray = fieldValue.Split(new char[] { ';' });
                                                foreach (var term in termsArray)
                                                {
                                                    termStrings.Add($"-1;#{term}");
                                                }
                                                updateValues.Add(new FieldUpdateValue(dataValue.Key, termStrings, dataField.TypeAsString));
                                            }
                                            break;
                                        }

                                        default:
                                        {
                                            //Publishing image case, but can be others too
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, fieldValue));
                                            break;
                                        }
                                        }
                                        break;

                                    default:
                                        updateValues.Add(new FieldUpdateValue(dataValue.Key, fieldValue));
                                        break;
                                    }
                                }
                            }

                            foreach (var itemValue in updateValues.Where(u => u.FieldTypeString != "TaxonomyFieldTypeMulti" && u.FieldTypeString != "TaxonomyFieldType"))
                            {
                                if (string.IsNullOrEmpty(itemValue.FieldTypeString))
                                {
                                    listitem[itemValue.Key] = itemValue.Value;
                                }
                            }
                            listitem.Update();
                            web.Context.Load(listitem);
                            web.Context.ExecuteQueryRetry();
                            foreach (var itemValue in updateValues.Where(u => u.FieldTypeString == "TaxonomyFieldTypeMulti" || u.FieldTypeString == "TaxonomyFieldType"))
                            {
                                switch (itemValue.FieldTypeString)
                                {
                                case "TaxonomyFieldTypeMulti":
                                {
                                    var field    = fields.FirstOrDefault(f => f.InternalName == itemValue.Key as string || f.Title == itemValue.Key as string);
                                    var taxField = web.Context.CastTo <TaxonomyField>(field);
                                    if (itemValue.Value != null)
                                    {
                                        var valueCollection = new TaxonomyFieldValueCollection(web.Context, string.Join(";#", itemValue.Value as List <string>), taxField);
                                        taxField.SetFieldValueByValueCollection(listitem, valueCollection);
                                    }
                                    else
                                    {
                                        var valueCollection = new TaxonomyFieldValueCollection(web.Context, null, taxField);
                                        taxField.SetFieldValueByValueCollection(listitem, valueCollection);
                                    }
                                    listitem.Update();
                                    web.Context.Load(listitem);
                                    web.Context.ExecuteQueryRetry();
                                    break;
                                }

                                case "TaxonomyFieldType":
                                {
                                    var field    = fields.FirstOrDefault(f => f.InternalName == itemValue.Key as string || f.Title == itemValue.Key as string);
                                    var taxField = web.Context.CastTo <TaxonomyField>(field);
                                    taxField.EnsureProperty(f => f.TextField);
                                    var taxValue = new TaxonomyFieldValue();
                                    if (itemValue.Value != null)
                                    {
                                        var termString = (itemValue.Value as List <string>).First();
                                        taxValue.Label    = termString.Split(new string[] { ";#" }, StringSplitOptions.None)[1].Split(new char[] { '|' })[0];
                                        taxValue.TermGuid = termString.Split(new string[] { ";#" }, StringSplitOptions.None)[1].Split(new char[] { '|' })[1];
                                        taxValue.WssId    = -1;
                                        taxField.SetFieldValueByValue(listitem, taxValue);
                                    }
                                    else
                                    {
                                        taxValue.Label    = string.Empty;
                                        taxValue.TermGuid = "11111111-1111-1111-1111-111111111111";
                                        taxValue.WssId    = -1;
                                        Field hiddenField = list.Fields.GetById(taxField.TextField);
                                        listitem.Context.Load(hiddenField, tf => tf.InternalName);
                                        listitem.Context.ExecuteQueryRetry();
                                        taxField.SetFieldValueByValue(listitem, taxValue);     // this order of updates is important.
                                        listitem[hiddenField.InternalName] = string.Empty;     // this order of updates is important.
                                    }
                                    listitem.Update();
                                    web.Context.Load(listitem);
                                    web.Context.ExecuteQueryRetry();
                                    break;
                                }
                                }
                            }
                            if (dataRow.Security != null && (dataRow.Security.ClearSubscopes == true || dataRow.Security.CopyRoleAssignments == true || dataRow.Security.RoleAssignments.Count > 0))
                            {
                                listitem.SetSecurity(parser, dataRow.Security);
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ex.GetType().Equals(typeof(ServerException)) &&
                                (ex as ServerException).ServerErrorTypeName.Equals("Microsoft.SharePoint.SPDuplicateValuesFoundException", StringComparison.InvariantCultureIgnoreCase) &&
                                applyingInformation.IgnoreDuplicateDataRowErrors)
                            {
                                scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_duplicate);
                                continue;
                            }
                            else
                            {
                                scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                    }
                }

                #endregion
            }

            return(parser);
        }