private TokenParser CreateSubSites(ProvisioningHierarchy hierarchy, TokenParser tokenParser, Model.SiteCollection sitecollection, ClientContext siteContext, Web web, TeamNoGroupSubSite subSiteObject)
        {
            var url = tokenParser.ParseString(subSiteObject.Url);

            var subweb = web.Webs.FirstOrDefault(t => t.ServerRelativeUrl.Equals(UrlUtility.Combine(web.ServerRelativeUrl, "/", url.Trim(new char[] { '/' }))));

            if (subweb == null)
            {
                subweb = web.Webs.Add(new WebCreationInformation()
                {
                    Language    = subSiteObject.Language,
                    Url         = url,
                    Description = tokenParser.ParseString(subSiteObject.Description),
                    Title       = tokenParser.ParseString(subSiteObject.Title),
                    UseSamePermissionsAsParentSite = subSiteObject.UseSamePermissionsAsParentSite,
                    WebTemplate = "STS#3"
                });
                WriteMessage($"Creating Sub Site with no Office 365 group at {url}", ProvisioningMessageType.Progress);
                siteContext.Load(subweb);
                siteContext.ExecuteQueryRetry();
            }
            else
            {
                WriteMessage($"Using existing Sub Site with no Office 365 group at {url}", ProvisioningMessageType.Progress);
            }

            if (subSiteObject.Sites.Any())
            {
                foreach (var subsubSite in subSiteObject.Sites)
                {
                    var subsubSiteObject = (TeamNoGroupSubSite)subsubSite;
                    tokenParser = CreateSubSites(hierarchy, tokenParser, sitecollection, siteContext, subweb, subsubSiteObject);
                }
            }

            return(tokenParser);
        }
        private TokenParser ApplySubSiteTemplates(ProvisioningHierarchy hierarchy, TokenParser tokenParser, Model.SiteCollection sitecollection, ClientContext siteContext, Web web, TeamNoGroupSubSite subSiteObject, ProvisioningTemplateApplyingInformation provisioningTemplateApplyingInformation)
        {
            var url = tokenParser.ParseString(subSiteObject.Url);

            var subweb = web.Webs.FirstOrDefault(t => t.ServerRelativeUrl.Equals(UrlUtility.Combine(web.ServerRelativeUrl, "/", url.Trim(new char[] { '/' }))));

            foreach (var templateRef in sitecollection.Templates)
            {
                var provisioningTemplate = hierarchy.Templates.FirstOrDefault(t => t.Id == templateRef);
                if (provisioningTemplate != null)
                {
                    provisioningTemplate.Connector = hierarchy.Connector;
                    if (tokenParser == null)
                    {
                        tokenParser = new TokenParser(subweb, provisioningTemplate);
                    }
                    else
                    {
                        tokenParser.Rebase(subweb, provisioningTemplate);
                    }
                    new SiteToTemplateConversion().ApplyRemoteTemplate(subweb, provisioningTemplate, provisioningTemplateApplyingInformation, true, tokenParser);
                }
                else
                {
                    WriteMessage($"Referenced template ID {templateRef} not found", ProvisioningMessageType.Error);
                }
            }

            if (subSiteObject.Sites.Any())
            {
                foreach (var subsubSite in subSiteObject.Sites)
                {
                    var subsubSiteObject = (TeamNoGroupSubSite)subsubSite;
                    tokenParser = ApplySubSiteTemplates(hierarchy, tokenParser, sitecollection, siteContext, subweb, subsubSiteObject, provisioningTemplateApplyingInformation);
                }
            }

            return(tokenParser);
        }
        public override ProvisioningHierarchy ExtractObjects(Tenant tenant, ProvisioningHierarchy hierarchy, ExtractConfiguration configuration)
        {
            ProvisioningHierarchy tenantTemplate     = new ProvisioningHierarchy();
            List <string>         siteCollectionUrls = configuration.Tenant.Sequence.SiteUrls;

            List <string> connectedSiteUrls = new List <string>();

            foreach (var siteCollectionUrl in siteCollectionUrls)
            {
                using (var siteContext = tenant.Context.Clone(siteCollectionUrl))
                {
                    if (configuration.Tenant.Sequence.IncludeJoinedSites && siteContext.Site.EnsureProperty(s => s.IsHubSite))
                    {
                        foreach (var hubsiteChildUrl in tenant.GetHubSiteChildUrls(siteContext.Site.EnsureProperty(s => s.Id)))
                        {
                            if (!connectedSiteUrls.Contains(hubsiteChildUrl) && !siteCollectionUrl.Contains(hubsiteChildUrl))
                            {
                                connectedSiteUrls.Add(hubsiteChildUrl);
                            }
                        }
                    }
                }
            }
            siteCollectionUrls.AddRange(connectedSiteUrls);

            ProvisioningSequence provisioningSequence = new ProvisioningSequence();

            provisioningSequence.ID = "TENANTSEQUENCE";
            foreach (var siteCollectionUrl in siteCollectionUrls)
            {
                var siteProperties = tenant.GetSitePropertiesByUrl(siteCollectionUrl, true);

                tenant.Context.Load(siteProperties);
                tenant.Context.ExecuteQueryRetry();
                Model.SiteCollection siteCollection = null;
                using (var siteContext = tenant.Context.Clone(siteCollectionUrl))
                {
                    siteContext.Site.EnsureProperties(s => s.Id, s => s.ShareByEmailEnabled);
                    var templateGuid = siteContext.Site.Id.ToString("N");
                    switch (siteProperties.Template)
                    {
                    case "SITEPAGEPUBLISHING#0":
                    {
                        siteCollection = new CommunicationSiteCollection();

                        siteCollection.IsHubSite = siteProperties.IsHubSite;
                        if (siteProperties.IsHubSite)
                        {
                            var hubsiteProperties = tenant.GetHubSitePropertiesByUrl(siteCollectionUrl);
                            tenant.Context.Load(hubsiteProperties);
                            tenant.Context.ExecuteQueryRetry();
                            siteCollection.HubSiteLogoUrl = hubsiteProperties.LogoUrl;
                            siteCollection.HubSiteTitle   = hubsiteProperties.Title;
                        }
                        siteCollection.Description = siteProperties.Description;
                        ((CommunicationSiteCollection)siteCollection).Language = (int)siteProperties.Lcid;
                        ((CommunicationSiteCollection)siteCollection).Owner    = siteProperties.OwnerEmail;
                        ((CommunicationSiteCollection)siteCollection).AllowFileSharingForGuestUsers = siteContext.Site.ShareByEmailEnabled;
                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_URL", siteProperties.Url);
                        ((CommunicationSiteCollection)siteCollection).Url = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_URL}}";
                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE", siteProperties.Title);
                        siteCollection.Title = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE}}";
                        break;
                    }

                    case "GROUP#0":
                    {
                        siteCollection           = new TeamSiteCollection();
                        siteCollection.IsHubSite = siteProperties.IsHubSite;
                        if (siteProperties.IsHubSite)
                        {
                            var hubsiteProperties = tenant.GetHubSitePropertiesByUrl(siteCollectionUrl);
                            tenant.Context.Load(hubsiteProperties);
                            tenant.Context.ExecuteQueryRetry();
                            siteCollection.HubSiteLogoUrl = hubsiteProperties.LogoUrl;
                            siteCollection.HubSiteTitle   = hubsiteProperties.Title;
                        }
                        siteCollection.Description = siteProperties.Description;

                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_ALIAS", siteProperties.Url.Substring(siteProperties.Url.LastIndexOf("/")));
                        ((TeamSiteCollection)siteCollection).Alias       = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_ALIAS}}";
                        ((TeamSiteCollection)siteCollection).DisplayName = siteProperties.Title;
                        ((TeamSiteCollection)siteCollection).HideTeamify = Core.Sites.SiteCollection.IsTeamifyPromptHiddenAsync(siteContext).GetAwaiter().GetResult();

                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE", siteProperties.Title);
                        siteCollection.Title = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE}}";
                        break;
                    }

                    case "STS#3":
                    {
                        siteCollection           = new TeamNoGroupSiteCollection();
                        siteCollection.IsHubSite = siteProperties.IsHubSite;
                        if (siteProperties.IsHubSite)
                        {
                            var hubsiteProperties = tenant.GetHubSitePropertiesByUrl(siteCollectionUrl);
                            tenant.Context.Load(hubsiteProperties);
                            tenant.Context.ExecuteQueryRetry();
                            siteCollection.HubSiteLogoUrl = hubsiteProperties.LogoUrl;
                            siteCollection.HubSiteTitle   = hubsiteProperties.Title;
                        }
                        siteCollection.Description = siteProperties.Description;
                        ((TeamNoGroupSiteCollection)siteCollection).Language   = (int)siteProperties.Lcid;
                        ((TeamNoGroupSiteCollection)siteCollection).Owner      = siteProperties.OwnerEmail;
                        ((TeamNoGroupSiteCollection)siteCollection).TimeZoneId = siteProperties.TimeZoneId;
                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_URL", siteProperties.Url);
                        ((TeamNoGroupSiteCollection)siteCollection).Url = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_URL}}";
                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE", siteProperties.Title);
                        siteCollection.Title = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE}}";
                        break;
                    }
                    }
                    var siteTemplateCreationInfo = new ProvisioningTemplateCreationInformation(siteContext.Web);

                    // Retrieve the template for the site
                    if (configuration != null)
                    {
                        siteTemplateCreationInfo = configuration.ToCreationInformation(siteContext.Web);
                    }
                    var siteTemplate = siteContext.Web.GetProvisioningTemplate(siteTemplateCreationInfo);
                    siteTemplate.Id = $"TEMPLATE-{templateGuid}";
                    if (siteProperties.HubSiteId != null && siteProperties.HubSiteId != Guid.Empty && siteProperties.HubSiteId != siteContext.Site.Id && siteTemplate.WebSettings != null)
                    {
                        siteTemplate.WebSettings.HubSiteUrl = $"{{parameter:SITECOLLECTION_{siteProperties.HubSiteId.ToString("N")}_URL}}";
                    }
                    tenantTemplate.Templates.Add(siteTemplate);

                    siteCollection.Templates.Add(siteTemplate.Id);

                    if (siteProperties.WebsCount > 1 && configuration.Tenant.Sequence.IncludeSubsites)
                    {
                        var webs         = siteContext.Web.EnsureProperty(w => w.Webs);
                        int currentDepth = 1;
                        foreach (var subweb in webs)
                        {
                            siteCollection.Sites.Add(ParseSubsiteSequences(subweb, ref tenantTemplate, configuration, currentDepth, configuration.Tenant.Sequence.MaxSubsiteDepth));
                        }
                    }
                    provisioningSequence.SiteCollections.Add(siteCollection);
                }
            }

            tenantTemplate.Sequences.Add(provisioningSequence);

            PnPProvisioningContext.Current.ParsedSiteUrls.Clear();
            PnPProvisioningContext.Current.ParsedSiteUrls.AddRange(siteCollectionUrls);

            return(tenantTemplate);
        }