|
| 1 | +import GeneratedFile from 'generator/GeneratedFile'; |
| 2 | +import FileGenerator from 'generator/FileGenerator'; |
| 3 | +import FindOrCreateCrontabXml from 'generator/util/FindOrCreateCrontabXml'; |
| 4 | +import { Uri } from 'vscode'; |
| 5 | +import { CronJobWizardData } from 'wizard/CronJobWizard'; |
| 6 | +import indentString from 'indent-string'; |
| 7 | +import Magento from 'util/Magento'; |
| 8 | +import HandlebarsTemplateRenderer from 'generator/HandlebarsTemplateRenderer'; |
| 9 | +import { MagentoScope } from 'types/global'; |
| 10 | +import { TemplatePath } from 'types/handlebars'; |
| 11 | + |
| 12 | +export default class CronJobXmlGenerator extends FileGenerator { |
| 13 | + public constructor(protected data: CronJobWizardData) { |
| 14 | + super(); |
| 15 | + } |
| 16 | + |
| 17 | + public async generate(workspaceUri: Uri): Promise<GeneratedFile> { |
| 18 | + const [vendor, module] = this.data.module.split('_'); |
| 19 | + const moduleDirectory = Magento.getModuleDirectory(vendor, module, workspaceUri); |
| 20 | + const etcDirectory = Uri.joinPath(moduleDirectory, 'etc'); |
| 21 | + const crontabFile = Uri.joinPath(etcDirectory, 'crontab.xml'); |
| 22 | + |
| 23 | + // Prepare cron job data |
| 24 | + const jobName = this.data.cronName; |
| 25 | + const jobInstance = `${vendor}\\${module}\\Cron\\${this.data.className}`; |
| 26 | + |
| 27 | + // Get or create crontab.xml content |
| 28 | + const crontabXml = await FindOrCreateCrontabXml.execute( |
| 29 | + workspaceUri, |
| 30 | + vendor, |
| 31 | + module, |
| 32 | + MagentoScope.Global |
| 33 | + ); |
| 34 | + |
| 35 | + // Create template renderer |
| 36 | + const renderer = new HandlebarsTemplateRenderer(); |
| 37 | + |
| 38 | + // Generate job XML using the template |
| 39 | + const jobXml = await renderer.render(TemplatePath.XmlCronJob, { |
| 40 | + jobName, |
| 41 | + jobInstance, |
| 42 | + cronSchedule: this.data.cronSchedule, |
| 43 | + }); |
| 44 | + |
| 45 | + // Check if group exists |
| 46 | + const groupExists = this.checkIfGroupExists(crontabXml, this.data.cronGroup); |
| 47 | + |
| 48 | + let insertXml: string; |
| 49 | + |
| 50 | + if (groupExists) { |
| 51 | + // Group exists, just use the job XML |
| 52 | + insertXml = indentString(jobXml, 4); |
| 53 | + } else { |
| 54 | + // Group doesn't exist, create it with the job XML |
| 55 | + insertXml = await renderer.render( |
| 56 | + TemplatePath.XmlCronGroup, |
| 57 | + { |
| 58 | + groupId: this.data.cronGroup, |
| 59 | + }, |
| 60 | + { |
| 61 | + groupContent: jobXml, |
| 62 | + } |
| 63 | + ); |
| 64 | + } |
| 65 | + |
| 66 | + // Find insertion position |
| 67 | + const insertPosition = this.getInsertPosition(crontabXml, this.data.cronGroup); |
| 68 | + |
| 69 | + // Insert new group |
| 70 | + const newCrontabXml = |
| 71 | + crontabXml.slice(0, insertPosition) + |
| 72 | + '\n' + |
| 73 | + indentString(insertXml, 4) + |
| 74 | + '\n' + |
| 75 | + crontabXml.slice(insertPosition); |
| 76 | + |
| 77 | + return new GeneratedFile(crontabFile, newCrontabXml, false); |
| 78 | + } |
| 79 | + |
| 80 | + /** |
| 81 | + * Check if group with given ID already exists |
| 82 | + */ |
| 83 | + private checkIfGroupExists(crontabXml: string, groupId: string): boolean { |
| 84 | + const groupRegex = new RegExp(`<group\\s+id=["']${groupId}["']`, 'i'); |
| 85 | + return groupRegex.test(crontabXml); |
| 86 | + } |
| 87 | + |
| 88 | + /** |
| 89 | + * Get position to insert new content |
| 90 | + */ |
| 91 | + private getInsertPosition(crontabXml: string, groupId: string): number { |
| 92 | + if (this.checkIfGroupExists(crontabXml, groupId)) { |
| 93 | + // If group exists, find position after group opening tag |
| 94 | + const groupRegex = new RegExp(`<group\\s+id=["']${groupId}["'][^>]*>`, 'i'); |
| 95 | + const match = groupRegex.exec(crontabXml); |
| 96 | + if (match) { |
| 97 | + return match.index + match[0].length; |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + // Otherwise insert before </config> |
| 102 | + return crontabXml.indexOf('</config>'); |
| 103 | + } |
| 104 | +} |
0 commit comments