Change `dateCreated` property to `datePublished`
[GitHub/WoltLab/WCF.git] / extra / migrate-shared-template.php
1 #!/usr/bin/env php
2 <?php
3 // @codingStandardsIgnoreFile
4
5 /**
6 * Helper script to migrate include templates to new shared templates in WoltLab Suite before 6.1.
7 * Replace in all `.tpl` files the `{include file='__oldTemplateName'}` with the new template name.
8 *
9 * @author Olaf Braun
10 * @copyright 2001-2024 WoltLab GmbH
11 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
12 * @package WoltLabSuite\Core
13 */
14
15 if (\PHP_SAPI !== 'cli') {
16 exit;
17 }
18
19 // old-template => new-template
20 $templates = [
21 '__wysiwygPreviewFormButton' => 'shared_wysiwygPreviewFormButton',
22 '__formButton' => 'shared_formButton',
23 '__wysiwygSmileyFormContainer' => 'shared_wysiwygSmileyFormContainer',
24 '__wysiwygTabMenuFormContainer' => 'shared_wysiwygTabMenuFormContainer',
25 '__formContainer' => 'shared_formContainer',
26 '__rowFormContainer' => 'shared_rowFormContainer',
27 '__rowFormFieldContainer' => 'shared_rowFormFieldContainer',
28 '__suffixFormFieldContainer' => 'shared_suffixFormFieldContainer',
29 '__tabFormContainer' => 'shared_tabFormContainer',
30 '__tabMenuFormContainer' => 'shared_tabMenuFormContainer',
31 '__tabTabMenuFormContainer' => 'shared_tabTabMenuFormContainer',
32 '__simpleAclFormField' => 'shared_simpleAclFormField',
33 '__aclFormField' => 'shared_aclFormField',
34 '__bbcodeAttributesFormField' => 'shared_bbcodeAttributesFormField',
35 '__emptyFormFieldDependency' => 'shared_emptyFormFieldDependency',
36 '__isNotClickedFormFieldDependency' => 'shared_isNotClickedFormFieldDependency',
37 '__nonEmptyFormFieldDependency' => 'shared_nonEmptyFormFieldDependency',
38 '__valueFormFieldDependency' => 'shared_valueFormFieldDependency',
39 '__valueIntervalFormFieldDependency' => 'shared_valueIntervalFormFieldDependency',
40 '__labelFormField' => 'shared_labelFormField',
41 '__contentLanguageFormField' => 'shared_contentLanguageFormField',
42 '__singleMediaSelectionFormField' => 'shared_singleMediaSelectionFormField',
43 '__pollOptionsFormField' => 'shared_pollOptionsFormField',
44 '__tagFormField' => 'shared_tagFormField',
45 '__userFormField' => 'shared_userFormField',
46 '__usernameFormField' => 'shared_usernameFormField',
47 '__userPasswordFormField' => 'shared_userPasswordFormField',
48 '__formFieldError' => 'shared_formFieldError',
49 '__wysiwygAttachmentFormField' => 'shared_wysiwygAttachmentFormField',
50 '__wysiwygFormField' => 'shared_wysiwygFormField',
51 '__numericFormField' => 'shared_numericFormField',
52 '__booleanFormField' => 'shared_booleanFormField',
53 '__buttonFormField' => 'shared_buttonFormField',
54 '__captchaFormField' => 'shared_captchaFormField',
55 '__checkboxFormField' => 'shared_checkboxFormField',
56 '__colorFormField' => 'shared_colorFormField',
57 '__dateFormField' => 'shared_dateFormField',
58 '__emailFormField' => 'shared_emailFormField',
59 '__hiddenFormField' => 'shared_hiddenFormField',
60 '__iconFormField' => 'shared_iconFormField',
61 '__itemListFormField' => 'shared_itemListFormField',
62 '__multilineTextFormField' => 'shared_multilineTextFormField',
63 '__multipleSelectionFormField' => 'shared_multipleSelectionFormField',
64 '__passwordFormField' => 'shared_passwordFormField',
65 '__radioButtonFormField' => 'shared_radioButtonFormField',
66 '__ratingFormField' => 'shared_ratingFormField',
67 '__selectFormField' => 'shared_selectFormField',
68 '__sourceCodeFormField' => 'shared_sourceCodeFormField',
69 '__uploadFormField' => 'shared_uploadFormField',
70 '__wysiwygSmileyFormNode' => 'shared_wysiwygSmileyFormNode',
71 '__form' => 'shared_form',
72 '__formContainerChildren' => 'shared_formContainerChildren',
73 '__formContainerDependencies' => 'shared_formContainerDependencies',
74 '__formField' => 'shared_formField',
75 '__formFieldDependencies' => 'shared_formFieldDependencies',
76 '__formFieldDescription' => 'shared_formFieldDescription',
77 '__formFieldErrors' => 'shared_formFieldErrors',
78 '__formFieldDataHandler' => 'shared_formFieldDataHandler',
79 '__singleSelectionFormField' => 'shared_singleSelectionFormField',
80 '__mediaSetCategoryDialog' => 'shared_mediaSetCategoryDialog',
81 '__messageQuoteManager' => 'shared_messageQuoteManager',
82 '__topReaction' => 'shared_topReaction',
83 '__wysiwygCmsToolbar' => 'shared_wysiwygCmsToolbar',
84 'aclPermissionJavaScript' => 'shared_aclPermissionJavaScript',
85 'aclSimple' => 'shared_aclSimple',
86 'articleAddDialog' => 'shared_articleAddDialog',
87 'benchmark' => 'shared_benchmark',
88 'booleanOptionType' => 'shared_booleanOptionType',
89 'booleanSearchableOptionType' => 'shared_booleanSearchableOptionType',
90 'captcha' => 'shared_captcha',
91 'categoryOptionList' => 'shared_categoryOptionList',
92 'checkboxesOptionType' => 'shared_checkboxesOptionType',
93 'checkboxesSearchableOptionType' => 'shared_checkboxesSearchableOptionType',
94 'codeMetaCode' => 'shared_codeMetaCode',
95 'codemirror' => 'shared_codemirror',
96 'colorPickerJavaScript' => 'shared_colorPickerJavaScript',
97 'fontAwesomeJavaScript' => 'shared_fontAwesomeJavaScript',
98 'formError' => 'shared_formError',
99 'formNotice' => 'shared_formNotice',
100 'formSuccess' => 'shared_formSuccess',
101 'languageChooser' => 'shared_languageChooser',
102 'lineBreakSeparatedTextOptionType' => 'shared_lineBreakSeparatedTextOptionType',
103 'mediaManager' => 'shared_mediaManager',
104 'messageFormAttachments' => 'shared_messageFormAttachments',
105 'messageTableOfContents' => 'shared_messageTableOfContents',
106 'multipleLanguageInputJavascript' => 'shared_multipleLanguageInputJavascript',
107 'passwordStrengthLanguage' => 'shared_passwordStrengthLanguage',
108 'quoteMetaCode' => 'shared_quoteMetaCode',
109 'radioButtonSearchableOptionType' => 'shared_radioButtonSearchableOptionType',
110 'recaptcha' => 'shared_recaptcha',
111 'scrollablePageCheckboxList' => 'shared_scrollablePageCheckboxList',
112 'sitemapEnd' => 'shared_sitemapEnd',
113 'sitemapEntry' => 'shared_sitemapEntry',
114 'sitemapIndex' => 'shared_sitemapIndex',
115 'sitemapStart' => 'shared_sitemapStart',
116 'trophyImage' => 'shared_trophyImage',
117 'unfurlUrl' => 'shared_unfurlUrl',
118 'uploadFieldComponent' => 'shared_uploadFieldComponent',
119 'userBBCodeTag' => 'shared_bbcode_user',
120 'userConditions' => 'shared_userConditions',
121 'userOptionsCondition' => 'shared_userOptionsCondition',
122 'worker' => 'shared_worker',
123 'wysiwyg' => 'shared_wysiwyg',
124 'groupBBCodeTag' => 'shared_bbcode_group',
125 '__videoAttachmentBBCode' => 'shared_bbcode_attach_video',
126 '__audioAttachmentBBCode' => 'shared_bbcode_attach_audio',
127 'mediaBBCodeTag' => 'shared_bbcode_wsm',
128 'articleBBCodeTag' => 'shared_bbcode_wsa',
129 '__multiPageCondition' => 'shared_multiPageCondition',
130 ];
131 if ($argc !== 2) {
132 echo "ERROR: Expected a single argument to the directory that should be used to recursively replace template includes.\n";
133 exit(1);
134 }
135 $directory = realpath($argv[1]);
136 if (!is_dir($directory)) {
137 echo "ERROR: The provided directory does not exist or is not accessible.\n";
138 exit(1);
139 }
140
141 function replaceInFiles(string $path): int
142 {
143 $directory = new RecursiveDirectoryIterator($path);
144 $filter = new RecursiveCallbackFilterIterator(
145 $directory,
146 function (SplFileInfo $current) {
147 $filename = $current->getFilename();
148 if ($filename === '.' || $filename === '..') {
149 return false;
150 }
151
152 if ($current->isDir()) {
153 return true;
154 }
155
156 $fileExtension = pathinfo($filename, PATHINFO_EXTENSION);
157 return $fileExtension === 'tpl';
158 }
159 );
160
161 $updatedFiles = 0;
162
163 $iterator = new RecursiveIteratorIterator($filter);
164 foreach ($iterator as $fileInfo) {
165 \assert($fileInfo instanceof SplFileInfo);
166 if (replaceTemplateInclude($fileInfo->getPathname())) {
167 $updatedFiles++;
168 }
169 }
170
171 return $updatedFiles;
172 }
173
174 function replaceTemplateInclude(string $filename): bool
175 {
176 global $templates;
177 $content = file_get_contents($filename);
178 $content = preg_replace_callback(
179 '~\{include.*(?<fileInclude>file=[\'\"](?<templateName>' . \implode('|', \array_keys($templates)) . ')[\'\"]).*}~',
180 function (array $matches) use ($templates): string {
181 [
182 'fileInclude' => $fileInclude,
183 'templateName' => $templateName
184 ] = $matches;
185 if (!isset($templates[$templateName])) {
186 return $matches[0];
187 }
188 // replace the old template name with the new one
189 return str_replace(
190 $fileInclude,
191 str_replace($templateName, $templates[$templateName], $fileInclude),
192 $matches[0]
193 );
194 },
195 $content,
196 -1,
197 $count
198 );
199
200 if ($count > 0) {
201 file_put_contents($filename, $content);
202 return true;
203 }
204
205 return false;
206 }
207
208 $replacedFiles = replaceInFiles($directory);
209 echo "Replaced {$replacedFiles} files.\n";