public EventHandler() { // read app.config var appConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location); _metadataXmlFieldName = appConfig.AppSettings.Settings["MetadataXmlFieldName"].Value; _mountpointType = appConfig.AppSettings.Settings["MountpointType"].Value; _asynchronous = Convert.ToBoolean(appConfig.AppSettings.Settings["Asynchronous"].Value); _update = Convert.ToBoolean(appConfig.AppSettings.Settings["Update"].Value); // build list of media manager mountpoint ids MountPointIds = new List <string>(); // read ExternalContentLibrary.xml from ..\Tridion\config folder XDocument eclConfig = XDocument.Load(string.Format(EclConfigFile, ConfigurationSettings.GetTcmHomeDirectory())); // loop over all mountpoints with configured type (could be multiple mountpoints) and add its id to our list foreach (XElement mountpoint in eclConfig.Descendants(EclNs + "MountPoint").Where(mountpoint => mountpoint.Attribute("type").Value.Equals(_mountpointType))) { MountPointIds.Add(mountpoint.Attribute("id").Value); } if (_asynchronous) { // subscribe to component checkin for asynchronous event (creates an extra version of the component, but has no performance impact on save) EventSystem.SubscribeAsync <Component, CheckInEventArgs>(SetOrUpdateMetadata, EventPhases.TransactionCommitted); } else { // subscribe to component save for synchronous event (has performance impact on save, only use if custom code is fast) EventSystem.Subscribe <Component, SaveEventArgs>(SetOrUpdateMetadata, EventPhases.Processed); } }
public override void Transform(Engine engine, Package package) { Initialize(engine, package); _mergeFileLines.Add("src\\system\\assets\\less\\_custom.less", new List <string>()); _mergeFileLines.Add("src\\system\\assets\\less\\_modules.less", new List <string>()); _mergeFileLines.Add("src\\templates\\partials\\module-scripts-header.hbs", new List <string>()); _mergeFileLines.Add("src\\templates\\partials\\module-scripts-footer.hbs", new List <string>()); _mergeFileLines.Add("src\\templates\\partials\\module-scripts-xpm.hbs", new List <string>()); StringBuilder publishedFiles = new StringBuilder(); string drive = package.GetValue("drive") ?? String.Empty; string cleanup = package.GetValue("cleanup") ?? String.Empty; // not using System.IO.Path.GetTempPath() because the paths in our zip are already quite long, // so we need a very short temp path for the extract of our zipfile to succeed // using current time and convert to hex (the date won't matter as this folder is cleaned up so time is unique enough) int timestamp = Convert.ToInt32(DateTime.Now.ToString("HHmmssfff")); if (!String.IsNullOrEmpty(drive) && Char.IsLetter(drive.First())) { _tempFolder = drive.First() + @":\_" + timestamp.ToString("x"); } else { // using drive from tridion cm homedir for temp folder _tempFolder = ConfigurationSettings.GetTcmHomeDirectory().Substring(0, 3) + "_" + timestamp.ToString("x"); } try { // read values from Component Component config = GetComponent(); ItemFields fields = new ItemFields(config.Content, config.Schema); Component favicon = fields.GetMultimediaLink("favicon"); string version = fields.GetTextValue("version"); string url = PublishJson(String.Format("{{\"version\":{0}}}", JsonEncode(version)), config, GetPublication().RootStructureGroup, "version", "version"); publishedFiles.AppendCommaSeparated(url); Logger.Info("Published " + url); // create temp folder Directory.CreateDirectory(_tempFolder); Logger.Debug("Created " + _tempFolder); // unzip and merge files ProcessModules(); // build html design string user = System.Security.Principal.WindowsIdentity.GetCurrent().Name; ProcessStartInfo info = new ProcessStartInfo { FileName = "cmd.exe", Arguments = "/c npm start --color=false", WorkingDirectory = _tempFolder, CreateNoWindow = true, ErrorDialog = false, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, StandardErrorEncoding = Encoding.UTF8, StandardOutputEncoding = Encoding.UTF8 }; using (Process cmd = new Process { StartInfo = info }) { cmd.Start(); using (StreamReader reader = cmd.StandardOutput) { string output = reader.ReadToEnd(); if (!String.IsNullOrEmpty(output)) { Logger.Info(output); // TODO: check for errors in standard output and throw exception } } using (StreamReader reader = cmd.StandardError) { string error = reader.ReadToEnd(); if (!String.IsNullOrEmpty(error)) { Exception ex = new Exception(error); ex.Data.Add("Filename", info.FileName); ex.Data.Add("Arguments", info.Arguments); ex.Data.Add("User", user); // TODO: check for known errors and throw exception with a user friendly message //if (error.ToLower().Contains("something")) //{ // throw new Exception(String.Format("Something went wrong for user {0}.", user), ex); //} throw ex; } } cmd.WaitForExit(); } // publish all binaries from dist folder string dist = Path.Combine(_tempFolder, "dist"); if (Directory.Exists(dist)) { // save favicon to disk (if available) if (favicon != null) { string ico = Path.Combine(dist, "favicon.ico"); File.WriteAllBytes(ico, favicon.BinaryContent.GetByteArray()); Logger.Debug("Saved " + ico); } string[] files = Directory.GetFiles(dist, "*.*", SearchOption.AllDirectories); foreach (string file in files) { string filename = Path.GetFileName(file); string extension = Path.GetExtension(file); Logger.Debug("Found " + file); // determine correct structure group Publication pub = (Publication)config.ContextRepository; string relativeFolderPath = file.Substring(dist.Length, file.LastIndexOf('\\') - dist.Length); Logger.Debug("Relative path: " + relativeFolderPath); relativeFolderPath = relativeFolderPath.Replace("system", SystemSgName).Replace('\\', '/'); string pubSgWebDavUrl = pub.RootStructureGroup.WebDavUrl; string publishSgWebDavUrl = pubSgWebDavUrl + relativeFolderPath; Logger.Debug("Structure Group WebDAV URL: " + publishSgWebDavUrl); StructureGroup sg = engine.GetObject(publishSgWebDavUrl) as StructureGroup; if (sg == null) { throw new Exception("Missing Structure Group " + publishSgWebDavUrl); } // add binary to package and publish using (FileStream fs = File.OpenRead(file)) { Item binaryItem = Package.CreateStreamItem(GetContentType(extension), fs); Binary binary = engine.PublishingContext.RenderedItem.AddBinary(binaryItem.GetAsStream(), filename, sg, "dist-" + filename, config, GetMimeType(extension)); binaryItem.Properties[Item.ItemPropertyPublishedPath] = binary.Url; package.PushItem(filename, binaryItem); publishedFiles.AppendCommaSeparated("\"{0}\"", binary.Url); Logger.Info("Published " + binary.Url); } } } else { throw new Exception("Grunt build failed, dist folder is missing."); } } finally { if (String.IsNullOrEmpty(cleanup) || !cleanup.ToLower().Equals("false")) { // cleanup workfolder Directory.Delete(_tempFolder, true); Logger.Debug("Removed " + _tempFolder); } else { Logger.Debug("Did not cleanup " + _tempFolder); } } // output json result package.PushItem(Package.OutputName, package.CreateStringItem(ContentType.Text, String.Format(JsonOutputFormat, publishedFiles))); }